views:

368

answers:

3

I have to do quite some cleanup in my OnClosing handler, which makes it seem like my app is hanging.

How can I show a small dialog with a marquee-style progressbar so users will at least know it's still 'working' ?

Basicly I want to start the dialog, proceed with all my shutdown-procedures and when that's done, close the progress-dialog.

A: 

Have you tried something like:

  private void Form1_FormClosing( object sender, FormClosingEventArgs e )
  {
     using ( Form2 myForm2 = new Form2() )
     {
        myForm2.Show();

        //Do your stuff here

        myForm2.Close();
     }
  }
msergeant
A: 

Is the code running in your shutdown really that important that you want your users to wait for it to complete before you give them back their screen real estate? Remember that the OS will clean up most of your application for you when you quit, so what do you really need to do?

If the cleanup is not that important, let the OS do it. Remove event handlers from the GUI, disable writing to files/databases and then just close the application. If your threads are all background they will be killed by the OS.

If the cleanup is important, have you considered what would happen if your application crashed suddenly instead of being shut down properly? If you want to be crash tolerant, you can't do important things in your shutdown code.

Mark Byers
Yes, the cleanup is that important.I have to wait for threads to finish, save a *lot* of data, etcetera - and it would be better if the user didn't kill it while shutting down ;)
Pygmy
Most programs that handle important data save it *all the time*. If you have only one copy in memory and the power fails, all that "important" data is lost. Oops.
Mark Byers
+2  A: 

There are many ways to achieve this, but one could looke like this:

protected override void OnClosing(CancelEventArgs e)
{
    base.OnClosing(e);

    Form dlg=null;
    ThreadPool.QueueUserWorkItem(state => {
        dlg = new ShuttingDownUI();
        dlg.ShowDialog();
    });

    // do hard work with saving and stuff

    if (dlg != null)
    {
        dlg.BeginInvoke((Action) dlg.Close);
    }
}

In the OnClosing method of your form, open a "shutting down dialog" on a separate thread containing a ProgressBar with its Style property set to Marquee. Then go on and do your saving/closing down procedure, and when you are done, close the "shutting down" dialog.

The important thing is that the form with the marquee must be on a separate thread than the one where the work is being done. Otherwise it will not animate, and the app will still appear as if it is not responding.

Fredrik Mörk
+1 for non-blocking
Michael G
+ BeginInvoke can be shortened to dlg.BeginInvoke((Action)dlg.Close);
Michael G
@Michael: thanks, didn't think about that. Edited.
Fredrik Mörk
Brilliant, thanks a lot !Just curious, is it possible that for some reason the created thread stalls and creates the dialog after the (dlg!=null) check ?(Suppose that for once I have a quick shutdownsequence ? :))
Pygmy