Home > Articles > Programming > Windows Programming

  • Print
  • + Share This
From the author of

Marshalling Background Threads to Foreground Threads

If we were to report the thread being used in ProgressChanged, you would likely see that the thread ID indicated is a completely different thread. In our console application, this situation causes no problems because the static Console methods are thread-safe. But Windows Forms controls are not thread-safe. Fortunately, there is a solution.

When you’re using the BackgroundWorker component in Windows Forms, every control has an InvokeRequired property. If you check InvokeRequired and it returns True, you need to marshal the background thread’s data onto the control’s thread, using Control.Invoke and passing the address of a delegate and the data. If you don’t do this, it’s just like driving without a seatbelt: Eventually you’re going to crash, and the result won’t be pretty.

Listing 5 demonstrates how we can have a form with a progress bar control and safely update the percentage complete by using Control.Invoke.

Listing 5 Updating a progress bar from a background thread by using Invoke.

Public Class Progress

 Private Shared form As Progress

 Public Shared Sub UpdateProgress(ByVal percent As Integer)
  If (form Is Nothing) Then form = New Progress
  form.Show()
  form.ProgressUpdater(percent)
 End Sub

 Public Delegate Sub Updater(ByVal percent As Integer)

 Private Sub ProgressUpdater(ByVal percent As Integer)
  If (InvokeRequired) Then Invoke( _
   New Updater(AddressOf ProgressUpdater), percent)

  ProgressBar1.Value = percent

 End Sub

 Public Shared Sub Finished()
  form.Close()
  form = Nothing
 End Sub

 Private Sub Progress_Load(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load

  ProgressBar1.Minimum = 1
  ProgressBar1.Maximum = 100

 End Sub
End Class

The class Progress is a Windows Form with a progress bar control on it. All of the interesting behavior happens in the method ProgressUpdater. ProgressUpdater checks InvokeRequired; if it is required, it calls itself recursively using the Form’s Invoke method and passing itself as the target of invocation. If Invoke is not required, the progress bar is simply updated.

It’s worth noting that after we call Invoke, the InvokeRequired test should fail, and the progress bar is safely updated on the Form and ProgressBar’s thread. It’s also worth mentioning that anonymous methods were invented to reduce the number of times that event handlers need to be created simply to support a cross-thread invoke call.

  • + Share This
  • 🔖 Save To Your Account