Using BackgroundWorker

T

Tim Anderson

I've been experimenting with the BackgroundWorker class. As a test, I've
built an application that searches for files matching a RegEx and populates
a listbox with the results.

My approach is to search directories recursviely andcall ReportProgress once
per directory or in batches of 10 matching files if there are a lot of
results. I pass an ArrayList containing the matching filenames. In the
ProgressChanged event handler I add the matching filenames to a listbox.

When I first ran the app, and if I use a blank RegEx matching all files, I
was surprised to find the UI frozen during the search just as if I were not
using BackgroundWorker. I've found I can fix this by inserting a call to
Thread.Sleep(1) just after I call ReportProgress.

Can someone explain why this is so?

Tim
 
G

Gabriel Lozano-Morán

The problem is adding the items to the listbox. Since gui controls are not
thread-safe this needs to be done on the main thread. By adding a sleep you
give the main thread the change to do other events.

Gabriel Lozano-Morán
 
T

Tim Anderson

Gabriel Lozano-Morán said:
The problem is adding the items to the listbox. Since gui controls are not
thread-safe this needs to be done on the main thread. By adding a sleep
you give the main thread the change to do other events.

I don't think it is quite that simple. I've done a bit more investigation.

The problem in a nutshell is that if you are (for example) matching every
file, then updating the GUI takes more time than doing the actual search.
ReportProgress is actually an async method, so what happens is that the next
call to ReportProgress comes before the GUI thread has actually finished
updating the GUI. The framework seems to sort this out so the app doesn't
actually crash, but the result is that the GUI thread is continuously busy
in the ProgressChanged event handler. The effect is a frozen UI.

I tried using the old Form.BeginInvoke approach instead of the
ReportProgress method. This has the same problem if I omit the call to
Form.EndInvoke - the GUI freezes. However, if I include a call to EndInvoke
in my GUI update method, it solves the problem. The GUI stays responsive,
and there's no need to call Thread.Sleep. I don't know if there's a good way
to do this using ReportProgress. Comments welcome.

Tim
 
T

Tim Anderson

Tim Anderson said:
and there's no need to call Thread.Sleep. I don't know if there's a good
way to do this using ReportProgress. Comments welcome.

For example, I tried using a Semaphore to force ReportProgress to wait until
the ProgressChanged handler completed. This works fine too.

Tim
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top