I've got a form where I handle the FormClosing
event differently based on the CloseReason
. For example I'm minimizing the form on CloseReason.UserClosing
I'm programmatically calling the event when a specific value is returned from a WCF Service call and I'm calling Application.Exit()
from the notify icon contextmenu ItemClicked
event to close the App among some other conditions.
While my app worked as expected till now, always raising the FormClosing
event when Application.Exit()
was called, it doesn't behave like that after some changes I've made. Most of the times the app is closing without raising the event, and the few times that it is getting raised the code on the event is executed (database work, notify icon disposing) without exiting the form.
How can this happen?
Application. Exit( )". This method internally informs all message loops in application that you must terminate. Then this method wait to close all application windows till the message loops have been processed.
The Exit method stops all running message loops on all threads and closes all windows of the application. This method does not necessarily force the application to exit. The Exit method is typically called from within a message loop, and forces Run to return.
We can close every window using Application. Exit(); Using this method we can close hidden windows also.
Yes, this is possible. The Application.Exit() method iterates the forms in the Application.OpenForms collection to call their OnFormClosing() method. There's a bug in Winforms that makes that collection lose track of open forms. This code demonstrates it:
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);
}
}
Click the form to trigger the bug. Note how it reports 0 open forms and how you never saw the message box displayed in OnFormClosing.
It is the assignment to the ShowInTaskbar property that causes it. There are several such properties, I picked ShowInTaskbar because that's one you are likely to use when you have a NotifyIcon. RightToLeft is another one. These properties are special because they can only be specified when the window is created with the native CreateWindowEx() api function. Changing them requires Winforms to do something pretty heroic, it destroys the window and re-creates it. Unfortunately that also triggers the bug, destroying the window also gets the form removed from the OpenForms collection and it forgets to add it back.
Copy/paste the OnHandleCreated() method from this snippet into your form and set a breakpoint on it. It must trigger once, when the window is first created. When it triggers again and thus invoke the bug scenario you can look at the call stack to see what code in your class triggered it. You'll have to disable that code and find another way to do it. Setting the ShowInTaskbar property in the constructor is fine, it only goes bad when you assign it after the window was created, like in the Load event handler.
Well as stated here
The Form.Closed and Form.Closing events are not raised when the Application.Exit method is called to exit your application. If you have validation code in either of these events that must be executed, you should call the Form.Close method for each open form individually before calling the Exit method.
EDIT
Since you are using FormClosing
,in that case maybe you should try using the overload of Exit
which might help in determining the form which cancelled the exit and help you inspect the problem further.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With