What is a background worker?
A background worker allow the designer to offload some of processing on another thread, which can make the UI feel more responsive.
How to use a background worker.
For this demonstration you'll have to create a new windows application project, until you grasped the basics.
Add two buttons to the form, name them Start_Button & Stop_Button
Add a progress bar
Add a label, named lbl_Status
Add a Background worker.
Set then enable state of the stop button to False
In the properties of the background worker set the following properties to true.
WorkerSupportsCancellation & WorkerReportsProgress
Now view to code of the form and add the following code the top.
Dim m_CountTo As Integer = 0' How many time to loop.
Double Click on the start button and enter.
Private Sub Start_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Start_Button.Click 'Set the count to 30 m_CountTo = 30 ' Disable the start button Me.Start_Button.Enabled = False ' Enable to stop button Me.Stop_Button.Enabled = True ' Start the Background Worker working My_BgWorker.RunWorkerAsync() End Sub
Double Click the stop button
Private Sub Stop_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Stop_Button.Click ' Is the Background Worker do some work? If My_BgWorker.IsBusy Then 'If it supports cancellation, Cancel It If My_BgWorker.WorkerSupportsCancellation Then ' Tell the Background Worker to stop working. My_BgWorker.CancelAsync() End If End If ' Enable to Start Button Me.Start_Button.Enabled = True ' Disable to Stop Button Me.Stop_Button.Enabled = False End Sub
Then Next section of code is the code that is to be run in the background.
Private Sub My_BgWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles My_BgWorker.DoWork For i As Integer = 0 To m_CountTo ' Has the background worker be told to stop? If My_BgWorker.CancellationPending Then ' Set Cancel to True e.Cancel = True Exit For End If System.Threading.Thread.Sleep(1000) ' Sleep for 1 Second ' Report The progress of the Background Worker. My_BgWorker.ReportProgress(CInt((i / m_CountTo) * 100)) Next End Sub
Note: That the My_BgWorker.ReportProgress only excepts integer values between 0 to 100 inclusive. So you'll have to scale your value to this range.
Now to add the code to update the Progress Bar
Private Sub My_BgWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles My_BgWorker.ProgressChanged ' Update the progress bar Me.ProgressBar1.Value = e.ProgressPercentage End Sub
Now for the code that runs after the Background Worker is finished.
Private Sub My_BgWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles My_BgWorker.RunWorkerCompleted If e.Cancelled Then Me.Lbl_Status.Text = "Cancelled" Else Me.Lbl_Status.Text = "Completed" End If End Sub
Now that all it takes to use a Background Worker.
For the more adventurous of you
Let's use that label and display a percentage of completion.
Add this extra line of code to the DoWork procedure
My_BgWorker.ReportProgress(CInt((i / m_CountTo) * 100)) Me.Lbl_Status.Text = FormatPercent(i / m_CountTo, 2) ' Show Percentage in Label
And Run.
You get the following error Cross-thread operation not valid: Control 'Lbl_Status' accessed from a thread other than the thread it was created on.
Why?
Because we are using a background worker and we're attempting to access controls on a different thread (The UI or form).
VB.Net doesn't like use talking to objects on another thread directly, so have to go Indirectly through a intermediary called a Delegate
It is possible to turn it off and allow them but that's just asking for trouble.
I'll show you the proper and correct way to achieve this, by adding a new subroutine and a delegate.
A delegate helps to communicate to objects of a different thread;- It delegates the talking between the different threads.
Go back to the code and enter the following code.
' The delegate
Delegate Sub SetLabelText_Delegate(ByVal [Label] As Label, ByVal [text] As String)
' The delegates subroutine.
Private Sub SetLabelText_ThreadSafe(ByVal [Label] As Label, ByVal [text] As String)
' InvokeRequired required compares the thread ID of the calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If [Label].InvokeRequired Then
Dim MyDelegate As New SetLabelText_Delegate(AddressOf SetLabelText_ThreadSafe)
Me.Invoke(MyDelegate, New Object() {[Label], [text]})
Else
[Label].Text = [text]
End If
End Sub
To use comment out the line code in Do Work routine that caused the error, then enter the following.
My_BgWorker.ReportProgress(CInt((i / m_CountTo) * 100)) ' Me.Lbl_Status.Text = FormatPercent(i / m_CountTo, 2) SetLabelText_ThreadSafe(Me.Lbl_Status, FormatPercent(i / m_CountTo, 2))
And run, now you have the label displaying the percentage.
Now you have the Background Worker in your Code Ninja arsenal.






MultiQuote




|