Take the 2-minute tour ×

Is there a better way to handle the task of doing something after the user has chosen to exit a WinForms program than this :

[edit 1 : in response to comment by 'NoBugz] In this case there is no ControlBox on the Form, and there is a reason for putting one level of indirection in what happens when the user chooses to close the Form [/edit 1]

[edit 2 : in response to all comments as of GMT +7 18:35 January 20 ] Perhaps using fading out the MainForm is a simple illustration of what you might want do as the Application is being closed : the user cannot interact with that : it is self-evidently related to the user's decision to terminate the application. [/edit 2]

(use some form of threading ?) (implications for a multi-threaded app ?) (does this code "smell bad" ?)

    // 'shutDown is an external form-scoped boolean variable
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        // make sure we don't block Windows ShutDown
        // or other valid reasons to close the Form
        if (e.CloseReason != CloseReason.ApplicationExitCall) return;

        // test for 'shutDown flag set here
        if (shutDown) return;

        // cancel closing the Form this time through
        e.Cancel = true;

        // user choice : default = 'Cancel
        if (MessageBox.Show("Exit Application ?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.OK)
            // user says Exit : activate Timer, set the flag to detect Exit
            timer1.Enabled = true;
            shutDown = true;

Summary : In a very standard WinForms application (one MainForm launched in Program.cs in the standard way) : in the FormClosing Event handler of the MainForm :

  1. exit immediately (triggering the default behavior : which is to close the MainForm and exit the Application) if :

    a. the CloseReason is anything other CloseReason.ApplicationExitCall

    b. if a special boolean variable is set to true, or

  2. if no immediate exit : cancel the "first call" to FormClosing.

  3. the user then makes a choice, via MessageBox.Show dialog, to Exit the Application, or Cancel :

    a. if the user Cancels, of course, the Application stays "as is."

    b. if the user has chosen to 'Exit :

    1. set the special boolean flag variable to true

    2. run a Timer that does some special stuff.

    3. when the internal test in the Timer code detects the "special stuff" is done, it calls Application.Exit

share|improve this question
Don't make the user deal with this. She clicked the X to stop your program, she's already sure and doesn't need to be told that it might not be a good idea. –  Hans Passant Jan 19 '10 at 22:23
@nobugz Thanks for your comment; n this case, I omitted to say that there is no ControlBox on the Form. I'll edit that in. –  BillW Jan 20 '10 at 11:13
Wow, you really give her a hard time. –  Hans Passant Jan 20 '10 at 11:18
@nobugz Thanks for your comments ! This is, by design, on a client's request, a somewhat non-standard WinForms UI; there is a reason for the execution of certain code via a Timer's 'Tick event on closing the Application : visually, things do happen, but there is nothing that happens the end-user can interact with as the Application is being closed. And the addition of one required verification step in order to shut down the Application is part of the "spec." –  BillW Jan 20 '10 at 11:31
add comment

3 Answers

up vote 6 down vote accepted

My suggestions, both as a developer and a user:

A very fast task

  • Just do the task in the Closing event handler.

A less fast, but not incredibly slow task

  • Create a non-background thread (so it's not shut down when the application exits) with the task in the Closing event handler.
  • Let the application exit. Forms will go away, et cetera, but the process will keep running until the task is done.
  • Just remember to handle exceptions and such in that worker thread. And make sure that things doesn't crash if the user reopens your application before that task is done.

Slower tasks

  • In the Closing event handler, open a shutting-down-form and let the form itself close.
  • Do the task in the/behind the shutting-down-form while displaying some friendly progress and information.
  • Exit application when task is done.

Some untested example code. We are doing something similar to this in one of our applications. The task in our case is to store window properties (location, size, window state, et cetera) to a database.

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    // If it wasn't the user who asked for the closing, we just close
    if (e.CloseReason != CloseReason.UserClosing)

    // If it was the user, we want to make sure he didn't do it by accident
    DialogResult r = MessageBox.Show("Are you sure you want this?", 
                                     "Application is shutting down.",
    if (r != DialogResult.Yes)
        e.Cancel = true;

protected override void OnFormClosed(FormClosedEventArgs e)
    // Start the task
    var thread = new Thread(DoTask)
        IsBackground = false,
        Name = "Closing thread.",


private void DoTask()
    // Some task to do here
share|improve this answer
+1 Thanks for your comment ! Really like the way you broke out strategies by time consumed. Very good point about preventing re-opening (will consider making the app a Singleton). In this case there are side-effects on the UI as the MainForm/Application is closed, and "extra step" of requiring the user to confirm shutdown is a requirement. But what happens does fall in the "fast" category. –  BillW Jan 20 '10 at 13:00
@BillW: Don't prevent re-opening unless it is really necessary. There is almost nothing I hate more as a user than closing an app and then when trying to launch it again I get a message that it is already running. How to handle this depends a lot upon what that task of yours is though. (Will add some example code to my answer with what you can do in the closing event) –  Svish Jan 20 '10 at 13:26
Thanks, Svish, for the example code ! I am curious what the advantages are of over-riding the FormClosed event, and launching your "finalizer" thread there, rather than in the "default" FormClosed event of the Form. –  BillW Jan 20 '10 at 17:00
@BillW: Oh, that's just because those 3 methods in my code are actually spread across three classes. The MainForm_FormClosing event handler is in the actual MainForm. The OnFormClosed is in a different class that the MainForm inherits from and the DoTask method is in a totally different class. What it happens in our application is that when a form inherits from that special form, it will automatically save the forms location, size and state when it closes. The reason for the overriding is just because I think it is kind of recommended when dealing with form inheritance. I think :p –  Svish Jan 20 '10 at 19:45
add comment

I don't see anything "wrong" with this. My only recommendation would be to let the user know that the program is "shutting down" by raising a non-modal window or perhaps a notification toaster above the system tray.

share|improve this answer
+1 Thanks for your comment ! I like the idea of system tray notification, and will explore that. –  BillW Jan 20 '10 at 11:25
add comment

A couple of minor points:

  • I'd question the need for a timer: as the application is exiting anyway, and the user won't therefore expect the UI to be responsive, why not simply do the clean-up code on the UI thread? As suggested by @Dave Swersky, a little notification window during cleanup would be polite.

  • What happens if the application exit is triggered by a Windows shutdown or a user logoff?

share|improve this answer
Thanks for your comment ! In this case the Timer is required, and the application does not exit until the Timer business is finished. What's being done by code exceuted in the Timer 'Tick event is not something the user can interact with, by design : there are some "visual side-effects" of the application closing process, but, again, the user can only "see" them, not interact with them. –  BillW Jan 20 '10 at 11:34
add comment

Your Answer


