Page 1 of 1

The Background Worker How to use a background worker. Rate Topic: ***** 2 Votes

#1 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 1959
  • View blog
  • Posts: 8,704
  • Joined: 29-May 08

Post icon  Posted 23 February 2009 - 02:37 PM

The Background Worker

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. :ph34r:

Is This A Good Question/Topic? 4
  • +

Replies To: The Background Worker

#2 lowrent2000  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 25-February 09

Posted 08 April 2009 - 09:39 PM

Greetings,
Thanks for the post, very helpful. I want to run an event timer in the tool strip. Timer works if there is no event to time. Stops when the event starts. How would you exacute a timer event within the background manager. Tried this, no good. Thanks for any help you can give.

Public Class Form1
Dim startTime As DateTime
Dim span As TimeSpan = DateTime.Now.Subtract(startTime)
Dim clock As String

Private Sub Start_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Start_Button.Click
Me.bgwTimer.RunWorkerAsync()
End Sub

Private Sub bgwTimer_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwTimer.DoWork
Me.Timer1.Start()
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer1.Tick
Me.bgwTimer.ReportProgress(span.Milliseconds)
End Sub

Private Sub bgwTimer_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwTimer.ProgressChanged
clock = e.ToString
Me.ToolStripLabel1.Text = span.Minutes.ToString & ":" & _
span.Seconds.ToString & "." & span.Milliseconds
End Sub
End Class

Noi errors, just terminates at the do work event. other foreground and background events uneffectived.
Was This Post Helpful? 0
  • +
  • -

#3 KevinPrecht  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 12-May 09

Posted 15 May 2009 - 03:34 PM

I just would like to say that this is EXACTLY the information that I was trying to figure out on my own with starting individual threads and then trying to keep track of them.

thanks a bunch for this very clear and helpful tutorial!

Kevin

:)
Was This Post Helpful? 0
  • +
  • -

#4 Sc00by22  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 25
  • Joined: 09-September 09

Posted 15 September 2009 - 09:00 AM

Thanks so much! Exactly what I have been needing for ages!
Was This Post Helpful? 0
  • +
  • -

#5 Guest_Code Learner*


Reputation:

Posted 30 March 2010 - 05:50 AM

Awesome Tutorial.....Thanks a lot!!!
Was This Post Helpful? 0

#6 TheRafi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 02-October 10

Posted 02 October 2010 - 07:29 PM

Thank you so much for this great tutorial.

Here is a modification I made to update a listbox instead of the label

    ' The delegate
    Delegate Sub SetListBox_Delegate(ByVal [ListBox] As ListBox, ByVal [text] As String)

    ' The delegates subroutine.
    Private Sub SetListBox_ThreadSafe(ByVal [ListBox] As ListBox, 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 [ListBox].InvokeRequired Then
            Dim MyDelegate As New SetListBox_Delegate(AddressOf SetListBox_ThreadSafe)
            Me.Invoke(MyDelegate, New Object() {[ListBox], [text]})
        Else
            [ListBox].Items.Add([text])
        End If
    End Sub

This post has been edited by TheRafi: 02 October 2010 - 07:59 PM

Was This Post Helpful? 0
  • +
  • -

#7 mvdsa  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 29-November 11

Posted 08 December 2011 - 06:06 AM

hi tHERE\

Where do i put my code in now to load in the background.. or am i being stupid :)/>

All i want to do is load a very big Form with graphics which takes a few seconds to load ..
but it looks realy bad when loading.

Please help

This post has been edited by macosxnerd101: 06 May 2013 - 12:18 PM
Reason for edit:: Removed quote

Was This Post Helpful? 0
  • +
  • -

#8 dhaggy1980  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 21-May 12

Posted 28 May 2012 - 11:37 AM

Awesome Tut man I have been trying for days now to figure out this background worker to work with ftp and it works great. Except it slows down when I put a label in. It will still upload but, I think it uploads according to the labels text. I don't need that stupid label anyway LOL. But all in all it works great.
Was This Post Helpful? 0
  • +
  • -

#9 deavmi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-May 13

Posted 06 May 2013 - 12:15 PM

Dude keep your code in the same place, the cross-thread thing won't show up when you are running the application normally and not debugging in VB, it will work as fine.

This post has been edited by macosxnerd101: 06 May 2013 - 12:18 PM
Reason for edit:: Removed quote

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1