Multithreading and GUI updaing

J

Jon Brunson

I've got a worker thread which tells the GUI to update a progress bar as
it's updating records in a database (10,000+ records). I tried the
following methods, but none of them work quite right. Any other ideas?

1) Invoke - halts the worker thread while waiting for the GUI thread to
pickup the Invoke, which can cause a dead-lock situation (eg. the GUI
thread attempts to read from the db that the worker thread has locked
(Threading.Monitor) while it is updating)

2) Third thread - using a third thread to do the invoking doesn't work,
as the worker thread creates loads of them, and the execute out of
sequence, causing the progress bar's value to move about erratically)

3) GUI Timer - Have an object which holds the status of the update (eg,
the percentage complete) which the worker thread updates, and the GUI
thread reads from by means of a timer on a form - causes an overhead on
the GUI thread, and only get executed when nothing else on the GUI
thread is happening, which can cause the progress bar to not move for a
while, then jump up a long way.
 
P

Paul G. Tobey [eMVP]

How about a queue which can accept data from the worker thread and have it
read by the UI thread? You can either use a point-to-point message queue,
as implemented in the OS, or write your own queue such that the UI thread is
somehow notified, via a callback, maybe, when new data is now in the queue,
and the worker thread can simply drop new data into the queue without
waiting for someone to read it.

Paul T.
 
J

Jon Brunson

Sounds good Paul, but it's the how to notify the GUI thread that
something's changed that puzzles me. I thought about maybe having a GUI
Timer polling every 10th of a second to check the queue, but then if the
GUI thread hits a Threading.Monitor.Enter on an object that is locked,
it would mean the timer would stop, and the GUI would not get updated.

If only there were some way to raise an event on the GUI thread, from
another thread.
 
J

Jon Brunson

Thank for the tips Daniel, I'm using CF1.0 and both of the methods
you've mentioned use a third thread to Invoke the GUI thread, and at the
rate of my worker thread (the GUI can receive multiple status updates in
a second), I end up with load of these background threads, which then
invoke the GUI in the wrong sequence.
 
D

Daniel Moth

rate of my worker thread (the GUI can receive multiple status updates in a
I would question whether you need to update the UI more than once (maybe
twice) a second (unless you are writing games!). I had a situation like that
where I dropped updates if one already occurred less than 2 seconds ago
(unless it was the last update of course!).
I end up with load of these background threads, which then invoke the GUI
in the wrong sequence.
Can you post a sample demonstrating that? Both the method on my blog with a
Queue and the BackgroundWorker make sure the events are in sequence.

Cheers
Daniel
 
P

Paul G. Tobey [eMVP]

The queue class would be most general if it set an event (an operating
system event), when the queue had data in it. A second thread responsible
for notifying the UI could be waiting on that event and use Control.Invoke
to callback into whatever registered UI event handlers you wanted.

Paul T.
 

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