Posted  by 

Winforms Update Ui From Backgroundworker Progresschanged

Guide to using BackgroundWorker in C#. You have some complex calculation or maybe you're connecting to a slow server from your application and it blocks the UI thread. However, the background worker is not ideal if you need constant communication between the two threads. BackgroundWorker Component in WPF An overview of the BackgroundWorker component by JeremyBytes.com. Point, we can update our UI and do clean up (if required). So, let’s put our process into the background. I am updating a label text on a backgroundworker progressChanged event (literally one 1 line of code in this event callback). Its updating about 50 times in around 45 seconds and the issue is that the UI only seems to update about 10 times.

27 Jul 2011Apache

Popular belief (reinforced indirectly by MSDN) is that BackgroundWorker class will marshal the “progress” and “completed” events back to the calling thread. This turned out to be most certainly not true. A more restricted (and closer to reality) form of this belief is that if BackgroundWorker is spawned by a WPF UI thread, the events will be marshaled back to the UI thread. This is almost true. Read on.

BackgroundWorker uses SynchronizationContext.Post() to marshal progress and completed events. It captures the synchronization context of the current thread when you invoke RunorkerAsync() method. If current thread has no synchronization context, a default one will be created.

For WPF UI threads, the synchronization context (of type DispatcherSynchronizationContext) will indeed post the events back to the UI thread.

Since MicroSurvey CAD is an “all in one” CAD and calculations package, you can publish final or interim results directly from your software without exporting to another CAD program for finishing and plotting. Download, Calculate, Design, Draft, Check and Print - all incorporated into a productive field-to-finish package. Always download installs to your computer and run the install from there, never run the install over the web. To confirm you are running the latest version, you should see 'MicroSurvey CAD 2010' in the title bar and version 10,2,0,21 (August 12, 2010) in the About screen. MicroSurvey Release History and Downloads Links. Posted by Brian Sloman on 20 January 2009 04:38 PM. Desktop Products. Full Download; MicroSurvey CAD 2010 [Release Notes] [Other Languages] MicroSurvey CAD 2010 (v10.0.0) - June 9, 2009. MicroSurvey FieldGenius FieldGenius 10 [Online Help] - Version Release Date Release Notes Download Link. Office 2010 download. Demo Download. Land Survey Solutions. Microsurvey develops computer software for Land Surveyors, Civil Engineers, Seismic Surveyors, Mapping Professionals, Police Officers, and Accident Reconstruction Specialists in more than 100 countries across the globe. Call: 1-800-668-3312.

UI threadRunWorkerAsync()
Thread pool threadDoWork()
UI threadRunWorkerCompleted and ProgressChanged events

In background thread, or in main thread of a console application, the synchronization context will schedule event calls on a thread pool. So, typically, you will end up with 3 or more threads:

Calling threadRunWorkerAsync()
Thread pool thread #1DoWork()
Thread pool thread #2…nRunWorkerCompleted and ProgressChanged events

An interesting twist occurs if you run BackgroundWorker on a soon-to-be-come-UI-thread thread. Typically, it’s a main thread of your application before you called Application.Run(). Windows is not psychic, and it does not know what you are about to do. So, until you actually started a WPF application, your main thread is considered a regular thread, and default synchronization context will be used instead of DispatcherSynchronizationContext. Thus, your background worker events will not be marshalled back to the UI thread. Instead, they will be executed on a thread pool. If you touch UI in those callbacks, bad things will happen.

The workarounds are:

  • Don’t use background workers before Application.Run()
  • Use Dispatcher.BeginInvoke() inside suspect callbacks (however, be prepared that proponents of the myth may remove them as redundant)
  • Manually install DispatcherSynchronizationContext (don’t do this it at home; I did not try it, but I think it should work).
Active7 months ago

I've been searching and found that a good way to perform background work and update the GUI is using background workers. However, doing this (stupid) little task (counting from 1 to 10000) it doesn't update the label content but prints to the debug! (This is just a spike solution for another project of course..)

Here's the code:

Miguel Ribeiro

Winform Update Ui

Miguel Ribeiro
3,75014 gold badges41 silver badges67 bronze badges

3 Answers

The ProgressChanged event is raised on the UI thread, not the worker thread. In your code, the worker thread is doing almost nothing (just loop from 0 to 10000 and call ReportProgress), most of the work is done on the UI thread. Basically, you're sending too many progress notifications. Because of this, the UI thread is almost always busy and has no time to render the new content of the label.

Rendering in WPF is not performed immediately when you change a property of a control, it is done on a separate dispatcher frame, which is processed when the dispatcher has nothing more urgent to do, based on the priority of the task. The priority used for rendering has a value of 7 (DispatcherPriority.Render); the ProgressChanged event is marshalled to the UI thread with a priority of 9 (DispatcherPriority.Normal), as specified on MSDN. So the ProgressChanged notifications always have a higher priority than rendering, and since they keep coming, the dispatcher never has time to process the rendering tasks.

If you just decrease the frequency of the notifications, your app should work fine (currently you're sending 100 notifications for each percentage value, which is useless):

Thomas LevesqueThomas Levesque
243k57 gold badges520 silver badges689 bronze badges
Akash KavaAkash Kava
31.4k18 gold badges106 silver badges151 bronze badges

Try to change the label using womething like this:

Note that i'm not sure it will work. I can not test it now. If it does not work, let me know and I will delete the answer.

If you need the a canonical way to do exactly what you want, look at the Hath answer in this post: How do I update the GUI from another thread?

keepAlive
3,4554 gold badges12 silver badges25 bronze badges
BackgroundworkerWinforms Update Ui From Backgroundworker ProgresschangedJonathanJonathan

Android Update Ui From Thread

9,9674 gold badges47 silver badges84 bronze badges

Winforms Update Ui From Backgroundworker Progresschanged

Not the answer you're looking for? Browse other questions tagged wpfmultithreadinguser-interfacebackgroundworker or ask your own question.