September 24th, 2007
The .NET Framework 2.0 BackgroundWorker class makes it easy to code simple threading into your applications. However, a common question that gets asked in VB related forums is, “How do I update a control, or controls, from the worker thread?”. Many people seem to be in search of a simple explanation of how to do this. In this article we’ll create a quick and easy example program that will walk you through the steps.
First, we will need to create a new Windows application. On our form we’ll add two buttons, btnStart and btnCancel, a progress bar, prgThread, and a listbox, lstValues. You may also want to import System.ComponentModel into the project namespace or onto the form or you can just spell it out like I’m doing below.
Next we’re going to add code. First, we declare the BackgroundWorker object, TestWorker. Note that we’re declaring it with events so that the event structure is built automatically.
' Private WithEvents TestWorker As System.ComponentModel.BackgroundWorker ' '
Now, code is added for the start button, btnStart.
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click btnStart.Enabled = False btnCancel.Enabled = True lstValues.Items.Clear() prgThread.Value = 0 TestWorker = New System.ComponentModel.BackgroundWorker TestWorker.WorkerReportsProgress = True TestWorker.WorkerSupportsCancellation = True TestWorker.RunWorkerAsync() End Sub
First, we disable the start button and enable the cancel button. Next we reset the values for our listbox and and progressbar. Now we’re ready to create our BackgroundWorker object. Notice that we tell it that we want to have it report progress and support cancellation. Finally, we tell it to run the worker.
Here’s the code for our worker thread. This code is contained in the DoWork event. All it’s doing is looping 100 times and reporting the progress and sleeping 100ms between iterations. We also check for a cancellation state.
Private Sub TestWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles TestWorker.DoWork Dim ListText As String For Value As Integer = 0 To 100 If TestWorker.CancellationPending Then Exit For End If ListText = String.Concat("Item #", Value) TestWorker.ReportProgress(Value, ListText) Threading.Thread.Sleep(100) Next End Sub
You can also see that in the ReportProgress function call that we’re passing in the current value and a string.
Updating Form Controls
In the ProgressChanged event, we get to process our values from our DoWork method. Here’s the code:
Private Sub TestWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles TestWorker.ProgressChanged prgThread.Value = e.ProgressPercentage lstValues.Items.Add(e.UserState) End Sub '
In this routine, the progress bar and the listbox are updated with values from the worker thread. Remember that the UserState value is an object and will require conversion if you can’t use an object type.
Canceling the Worker
Now, what if you want to cancel the worker? Here’s the code that goes into our cancel button’s Click event:
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click TestWorker.CancelAsync() End Sub ' '
Here we call the CancelAsync method. However, this only sets a flag and, as shown above, our DoWork method has to check for a CancellationPending state. Otherwise, the work will continue until the DoWork routine is exited.
Finishing Things Up
When the work has been completed or canceled, the RunWorkerCompleted method is called. In our program, this allows us to reset our buttons.
Private Sub TestWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles TestWorker.RunWorkerCompleted btnStart.Enabled = True btnCancel.Enabled = False End Sub
That’s how it’s done in a nutshell. Of course, handling multi-threading in your applications can become very tricky. It is recommended that you further review how to avoid problems with threading before implementing it.
Let me know if you have any questions about BackgroundWorker or if you have any suggestions or thoughts about this example by leaving me a comment.
Rate This Article: