2012-11-23 2 views
5

Tôi có một biểu mẫu mà tôi xử lý sự kiện FormClosing khác nhau dựa trên CloseReason. Ví dụ tôi đang giảm thiểu biểu mẫu trên CloseReason.UserClosing Tôi đang lập trình gọi sự kiện khi một giá trị cụ thể được trả về từ cuộc gọi WCF Service và tôi gọi số Application.Exit() từ biểu tượng thông báo contextmenu ItemClicked sự kiện để đóng Ứng dụng trong một số điều kiện khác.Có trường hợp nào Application.Exit() không tăng sự kiện FormClosing không?

Trong khi ứng dụng của tôi hoạt động như mong đợi cho đến bây giờ, luôn tăng sự kiện FormClosing khi số Application.Exit() được gọi, nó không hoạt động như sau một số thay đổi tôi đã thực hiện. Hầu hết các lần ứng dụng đang đóng mà không cần tăng sự kiện và một vài lần nó được tăng mã trên sự kiện được thực thi (công việc cơ sở dữ liệu, thông báo hủy bỏ biểu tượng) mà không thoát khỏi biểu mẫu.

Điều này có thể xảy ra như thế nào?

+0

Tôi tìm thấy khi 'ShowInTaskbar = false;' rằng 'Application.Exit()' không kích hoạt sự kiện 'FormClosing', khi nó thường xảy ra. –

Trả lời

11

Có, điều này là có thể. Phương thức Application.Exit() lặp lại các biểu mẫu trong bộ sưu tập Application.OpenForms để gọi phương thức OnFormClosing() của chúng. Có một lỗi trong Winforms khiến cho bộ sưu tập đó mất dấu vết của các biểu mẫu mở. Mã này chứng minh điều đó:

public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 
    } 
    protected override void OnHandleCreated(EventArgs e) { 
     // Set breakpoint here: 
     base.OnHandleCreated(e); 
    } 
    protected override void OnMouseDown(MouseEventArgs e) { 
     this.ShowInTaskbar = !this.ShowInTaskbar; 
     MessageBox.Show(string.Format("There are {0} open forms", Application.OpenForms.Count)); 
     Application.Exit(); 
    } 
    protected override void OnFormClosing(FormClosingEventArgs e) { 
     MessageBox.Show("you won't see this"); 
     base.OnFormClosing(e); 
    } 
} 

Nhấp vào biểu mẫu để kích hoạt lỗi. Lưu ý cách nó báo cáo 0 biểu mẫu mở và cách bạn chưa bao giờ thấy hộp thông báo được hiển thị trong OnFormClosing.

Đây là nhiệm vụ cho thuộc tính ShowInTaskbar gây ra nó. Có một số thuộc tính như vậy, tôi đã chọn ShowInTaskbar vì đó là một trong những bạn có khả năng sử dụng khi bạn có một NotifyIcon. RightToLeft là một số khác. Các thuộc tính này đặc biệt vì chúng chỉ có thể được chỉ định khi cửa sổ được tạo bằng hàm api CreateWindowEx() gốc. Thay đổi chúng đòi hỏi Winforms phải làm một cái gì đó khá anh hùng, nó phá hủy cửa sổ và tạo lại nó. Thật không may mà cũng gây ra lỗi, phá hủy cửa sổ cũng bị loại bỏ khỏi bộ sưu tập OpenForms và nó quên để thêm nó trở lại.

Sao chép/dán phương thức OnHandleCreated() từ đoạn mã này vào biểu mẫu của bạn và đặt điểm ngắt trên đó. Nó phải kích hoạt một lần, khi cửa sổ được tạo ra lần đầu tiên. Khi nó kích hoạt một lần nữa và do đó gọi kịch bản lỗi bạn có thể nhìn vào ngăn xếp cuộc gọi để xem mã nào trong lớp của bạn đã kích hoạt nó. Bạn sẽ phải tắt mã đó và tìm cách khác để thực hiện. Đặt thuộc tính ShowInTaskbar trong hàm tạo là tốt, nó chỉ xấu khi bạn gán nó sau khi cửa sổ được tạo, như trong trình xử lý sự kiện Load.

+0

Cảm ơn, đó là thay đổi tôi đã thực sự thực hiện. Thuộc tính 'ShowInTaskbar' mà tôi đang thiết lập là true ở phần cuối của sự kiện' FormLoad' sau khi tất cả công việc cần được thực hiện trong khi tải ứng dụng kết thúc. Tôi sẽ xem xét nó. – Pantelis

+0

Những đặc tính nào khác có thể khiến điều này xảy ra? Tôi đã xóa cài đặt thuộc tính khỏi sự kiện FormLoad và nó vẫn xảy ra. Cách ít thường xuyên hơn, như một trong mười lần, nhưng nó vẫn xảy ra. – Pantelis

+0

Có một số trường hợp góc lẻ. Đây là lý do tại sao tôi đề nghị bạn gỡ lỗi nó với một breakpoint trên phương pháp OnHandleCreated. –

1

Vâng như stated here

Các Form.Closed và Form.Closing sự kiện không được nêu ra khi các phương pháp Application.Exit được gọi là để thoát khỏi ứng dụng của bạn. Nếu bạn có mã xác nhận trong một trong các sự kiện này phải được thực thi, bạn nên gọi phương thức Form.Close cho từng biểu mẫu mở riêng lẻ trước khi gọi phương thức Thoát.

EDIT

Vì bạn đang sử dụng FormClosing, trong trường hợp đó có lẽ bạn nên thử sử dụng sự quá tải của Exit mà có thể giúp đỡ trong việc xác định các hình thức mà hủy lối ra và giúp bạn kiểm tra các vấn đề tiếp theo.

+0

Có một vài hình thức phụ trong dự án nhưng không có biểu mẫu nào trong số đó được mở. Ngoài ra tôi không gọi sự kiện đóng cửa lỗi thời. Tôi đang gọi sự kiện FormClosing. – Pantelis

+0

Thoát thường bị hủy rất thường xuyên. Đối với phần lớn các lần thoát ứng dụng mà không tăng sự kiện 'FormClosing' của Biểu mẫu chính. – Pantelis

+0

@Pantelis, Tuy nhiên vẫn sử dụng WinForms obselete mặc dù. – Jodrell