Refreh form with progress indicator while in processing loop

  • Thread starter Thread starter Trees
  • Start date Start date
T

Trees

I have a form with a listbox. The listbox is updated with status text that
logs the progress of a tight loop that is executed from a button on the same
form.

The updates don't appear on the form until the processing is complete which
is 10 or more seconds later.

I'm not too surprised to see this.

I was wondering what the best practice technique is to give some processing
time back to the form so that it may update as the processing progresses?
 
I found Application.DoEvents(). I'm assuming this is the best practice
technique for now.
 
Application.DoEvents is a hack, and you have to be careful with it.

Realize that it causes _all_ UI events to be handled, so if the user
clicks on an enabled button while you're processing, calling
Application.DoEvents() will cause the _Click event handler for the
button to execute.

Imagine a nervous user tapping a button over and over again, causing
more and more loops to run, one within the other. To avoid this
scenario, you must disable all of the controls on your form before
starting your processing. I find that an easy way to do this is to put
all of my controls on one or two panels (if they aren't already) and
just disable the panels. Don't forget about disabling the menus, too.
Then, when you're done, you can enable the panels that you disabled to
restore control to the user. You should do this in a finally block (if
you're working in C#... I don't know what the VB.NET equivalent is).
The C# psuedocode looks like this:

EnableControls(false);
try
{
... do processing work, including calls to
Application.DoEvents()...
}
finally
{
EnableControls(true);
}

This guarantees that no matter what happens within your processing
loop, the controls will always be re-enabled. (I leave the
EnableControls method as an exercise for the reader. :-)

However, I said that Application.DoEvents() was a hack. Really, the
correct way to do this is using a background thread. You pass control
to the background thread to do the heavy processing. The method running
the background code can then either raise an event every now and then
to indicate how things are going, or call another method to update the
progress display directly. Note that the call must be Invoked back onto
the UI thread in order to update the progress display.

Then, when the background thread is done, it does an Invoke back onto
the UI thread to do any processing that has to occur after the
background work is done, such as re-enabling the controls.

You can read about background threading and Windows here:

http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
 
Back
Top