tags:

views:

67

answers:

3

If I have something like while (true) Application.DoEvents(); (it's really not exactly like that) and when I close the main form, the program stays running. How can I make the program stop running? Is there any variable like 'MustTerminate' that I can check in my while loop to know when to finish it? On real life the loop is waiting for a web page to load. I could put a timer but I don't want the program to wait for the timer to stop running if when I close the form.

A: 

Add yourself a boolean MustTerminate property, and exit the loop when you find it true. You can set the property to True handiling the ApplicationExit event.

Andrea Parodi
+2  A: 

Yes, this is the reason you'll always get advice to not use DoEvents(). It is far to indiscriminate about what kind of events it allows to run. Not just closing forms, pressing the button that starts that loop is a nasty problem as well.

Nevertheless, there is already code in .NET that uses DoEvents() in a loop. Form.ShowDialog(). It makes it safe by doing the equivalent of this:

foreach (Form frm in Application.OpenForms) {
    if (frm != dlg) frm.Enabled = false;
}
while (dlg.DialogResult != DialogResult.None) {
    Application.DoEvents();
}

Setting the Enabled property to false is what makes it safe. The user can't close forms or start the command again.

Hans Passant
+1 I ran afoul of ShowDialog() a few days ago by accidentally enabling the parent form. I didn't fully understand the logic then, but this clears it up.
Jonathan
A: 

Nested message loops are quite tricky. They have an uncanny ability to create re-entrancy bugs which are extremely difficult to reproduce. These bugs usually live for a considerable time until an unexpected situation occurs (an older machine, memory paging out, or a different OS) which reveals the latent bug - on client machines, naturally.

The best way to handle this kind of situation is to handle an event that is triggered when the operation is complete. If there is no event already defined, you can create your own by using the SynchronizationContext class or its wrapper the AsyncOperation class. See the MSDN docs on the event-based asynchronous pattern for more details.

Stephen Cleary