Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any cases where Application.Exit() doesn't raise the FormClosing event?

Tags:

c#

.net

winforms

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?

like image 681
Pantelis Avatar asked Nov 23 '12 09:11

Pantelis


People also ask

What is the purpose of using below command application exit();?

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.

What is application exit?

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.

Which of the following method is used to close the windows form application?

We can close every window using Application. Exit(); Using this method we can close hidden windows also.


2 Answers

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.

like image 157
Hans Passant Avatar answered Nov 15 '22 07:11

Hans Passant


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.

like image 37
V4Vendetta Avatar answered Nov 15 '22 07:11

V4Vendetta