Tuesday, September 20, 2011

Is BackgroundWorker really thread safe component for WinForms?

 
Under certain circumstances the BackgroundWorker Component's ProgressChanged event and RunWorkerCompleted event will run on the wrong thread
Microsoft claims (for updating the UI controls based on work that us getting done by background thread):

“The preferred way to implement multithreading in your desktop based application is to use the BackgroundWorker component. The BackgroundWorker component uses an event-driven model for multithreading. The background thread runs your DoWork event handler, and the thread that creates your controls runs your ProgressChanged and RunWorkerCompleted event handlers. You can call your controls from your ProgressChanged and RunWorkerCompleted event handlers.”
Claim link: http://msdn.microsoft.com/en-us/library/ms171728.aspx
 
But intermittently I have experienced under certain circumstances the BackgroundWorker Component's ProgressChanged event and RunWorkerCompleted event will run on the wrong thread (probably by worker thread itself). I was surprised by this. When these event run under wrong thread, I get cross thread error. So to solve this I had check under which thread these events are running and perform actions under the thread that has created the UI control. For this we need to use InvokeRequired property and Invoke method as shown below:

(This approach is what we follow if we use our own thread and not this component)

 
if(control.InvokeRequired)
  control.Invoke(Action);
else
  Action()
 
InvokeRequired:
Gets a value indicating whether the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on.
Invoke():
Executes the specified delegate on the thread that owns the control's underlying window handle.