Vinod Maurya
Vinod Maurya

Reputation: 4167

Other ways to update UI from thread in C#

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

Answers (4)

Dax Fohl
Dax Fohl

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

Brian Gideon
Brian Gideon

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.
  • The UI thread gets to dictate when and how often to update the form and its controls.
  • It eliminates the tight coupling between UI and worker threads that ISynchronizeInvoke imposes.
  • There is no risk of overrunning or saturating the UI message queue with a bunch of marshaling operations.
  • You get more throughput on the worker thread since it does not have to wait for response as would be the case with Invoke.

Upvotes: 2

Dax Fohl
Dax Fohl

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

Sogger
Sogger

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

Related Questions