This month i started a new software, it’s a SEO Analisys Tool, and i needed to threat multithreading and background operations handling. Giving a look inside the .Net Framework i found a very interesting class, the BackgroundWorker class. First of all i have to tell you where it’s placed, in most articles on the web they forget to tell the reader where he can find it. It’s placed into the System.ComponentModel namespace.
The BackgroundWorker class is a really simple to use class, it gives you the opportunity to handle multitasking in a very easy way.
Basic informations about the class
The BackgroundWorker class exposes just few events to control the status of the process an to notify what’s going on.
- DoWork (in this you’ll write all the code to execute)
- ProgressChanged (raised when the thread execution process changes)
- RunWorkerCompleted (when the thread job is finished)
All that you have to know is
- On the top of your code page include the System.ComponentModel namespace (imports System.ComponentModel)
- In the DoWork event write your code loop and remember to throw the ProgressChanged event if you need to handle it (RaiseEvent ProgressChanged(me)
- Handle the process cancellation in the DoWork loop checking for CancellationPending flag (if bgWork.CancellationPending then e.cancel)
- if you need the thread cancellation support you have to add a line of code to the New sub (bgWork.WorkerSupportsCancellation = true)
I know it seems too easy to be true but it’s really so…
Here you can find a sample piece of code to get download progress in vb.net
Or give a look at the code:
Option Strict Off
Imports System
Imports Microsoft.VisualBasic
Imports System.Windows.Forms
Imports System.Collections
Imports System.Threading
Imports System.Net
Imports System.Web.HttpUtility
Imports System.Text
Imports System.ComponentModel
Public Enum WebProcessStatus
Idle = 0
ReadingData = 1
DataReady = 2
PostingData = 3
DataPosted = 4
ReadingResult = 5
ResultReady = 6
Canceled = 7
ErrorReading = 8
End Enum
Public Class WebProcess
Public Status As WebProcessStatus
Public ActionName As String
Public URL As String
Public lastError As String = ""
Public sReadedHTML As String
Public Event BeginReading()
Public Event DataReaded(ByVal sender As Object)
Public Event ErrorReading()
Public Event ProgressChanged(ByVal sender As Object)
Public progressStatus As Integer = 0
Public WithEvents bgWork As New BackgroundWorker
Public isCanceled As Boolean = False
Public Sub New()
bgWork.WorkerSupportsCancellation = True
End Sub
Public Sub StopProcess()
isCanceled = True
bgWork.CancelAsync()
End Sub
Public Function IsReady() As Boolean
Select Case Status
Case WebProcessStatus.Idle, WebProcessStatus.DataReady, WebProcessStatus.ResultReady
Return True
Case Else
Return False
End Select
End Function
Public Sub BeginRead()
If Not bgWork.IsBusy Then
progressStatus = 0
bgWork.RunWorkerAsync()
End If
End Sub
Private Sub bgWork_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgWork.DoWork
If bgWork.CancellationPending Then
e.Cancel = True
End If
RaiseEvent BeginReading()
Try
Dim wRemote As System.Net.WebRequest
Dim bBuffer(999) As Byte
Dim iBytesRead As Integer
wRemote = System.Net.WebRequest.Create(URL)
Dim myWebResponse As System.Net.WebResponse = wRemote.GetResponse()
Dim scaricati As Integer
Dim dimensione As Integer
lastError = myWebResponse.ContentLength.ToString
If myWebResponse.ContentLength > -1 Then
dimensione = Convert.ToInt32(myWebResponse.ContentLength)
Else
dimensione = 200000
End If
Dim bReadedHTML(dimensione) As Byte
Dim sw As System.IO.MemoryStream = New System.IO.MemoryStream(bReadedHTML)
Dim sChunks As System.IO.Stream = myWebResponse.GetResponseStream
Do
iBytesRead = sChunks.Read(bBuffer, 0, 256)
lastError = "1"
scaricati += iBytesRead
lastError = "2"
If scaricati > dimensione Then
dimensione += 9062
ReDim bReadedHTML(dimensione)
End If
progressStatus = Convert.ToInt32((scaricati * 100) / dimensione)
If iBytesRead > 0 Then
sw.Write(bBuffer, 0, iBytesRead)
End If
RaiseEvent ProgressChanged(Me)
Application.DoEvents()
Loop While Not (iBytesRead = 0)
progressStatus = 100
RaiseEvent ProgressChanged(Me)
sChunks.Close()
sw.Close()
Dim objUTF8 As New UTF8Encoding()
sReadedHTML = objUTF8.GetString(bReadedHTML)
Catch
sReadedHTML = ""
progressStatus = 100
Status = WebProcessStatus.ErrorReading
RaiseEvent ErrorReading()
End Try
End Sub
Private Sub bgWork_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgWork.RunWorkerCompleted
' If e.Error.Message <> "" Then
'RaiseEvent ErrorReading()
'End If
If Not isCanceled Then
Status = WebProcessStatus.DataReady
Else
Status = WebProcessStatus.Canceled
End If
RaiseEvent DataReaded(Me)
End Sub
End Class
