Reputation: 4167
My application is heavily depended on threads to do the complex processing of very large data. The UI needs to be updated as the processing is being done. I know and tried to used BackgroundWorker's
OnProgressChanged
and RunWorkerCompleted
methods to update the UI. Also using Invoke
method of the UI thread to update. Everything seems to work fine on Win XP 32 bit and 64 bit OS. On Win Vista and Win 7 (32 and 64 bit), the application randomly hangs while updating the UI by using Invoke
method.
Does the behavior of Invoke
changes on different Win OS?
What are the other ways of updating UI from thread apart from Invoke
?
Thanks
Upvotes: 2
Views: 493
Reputation: 10781
Another option would be to forego the multithreading entirely. If your long-running operation can be broken up into chunks, do it in the GUI thread and use Application.DoEvents()
when you want to update the GUI.
I used to dislike use of that method since it could not only update the GUI but also start responding to user input, kicking off timers, etc., but ultimately it's no less safe than using a background thread, which allows the GUI to start doing anything at any time. So probably after each call of Application.DoEvents()
you'd need to check _canceled
or whatever. (I eventually decided I dislike the existence of this method, since it eliminates the guarantees of linear execution order, than the use of it).
Of course you lose multicore support this way, so it'd affect performance if you're trying to run lots of background ops at the same time.
Upvotes: 0
Reputation: 48949
Does the behavior of Invoke changes on different Win OS?
It should not, no. But, threading problems can materialize in very unpredictable ways. It is possible that you have an unidentified problem.
What are the other ways of updating UI from thread apart from Invoke?
Using Invoke
or BeginInvoke
are way overused especially when trying to report simple progress information to the UI thread. If you search for some of my answers related to the subject you will see that I rip on this approach all of the time. And for good reason since their are many disadvantages to using this technique. It is unfortunate that BackgroundWorker
uses this mechanism exclusively for updating the UI through its ProgressChanged
event.
One alternate method is to have your worker thread publish progress information into a shared variable and have the UI thread poll for it periodically via a timer. Here are some of my usual talking points in justifying this approach over the marshaling techniques.
Invoke
and BeginInvoke
are expensive operations.ISynchronizeInvoke
imposes.Invoke
.Upvotes: 2
Reputation: 10781
Not sure what's going wrong, but you could always just have a System.Windows.Forms.Timer
running that updates the GUI periodically; use some member variables to pass raw data between threads, inside locks if necessary. Not the most elegant solution, but it might give you a different perspective into what's hanging since the threads are more independent this way, rather than relying on a background thread to Invoke
your main thread.
Upvotes: 2
Reputation: 16132
You could try using one of the Invoke() or BeginInvoke() overloads that takes a Dispatcher.Priority enum as a parameter. If you select a parameter such as 'Background' you should see your application is still responsive. The only issue then becomes ensuring you are servicing your incoming data at an adequate rate without an ever increasing queue.
Upvotes: 1