Wednesday, November 5, 2008

Custom Backgroundworker with VB

Hi All,

Here is a sample code of how to create a class that implement a custom backgroundworker with VB.NET 2005/2008;
Prerequisite: you have to be familiar with Delegates and Events.

1-Create a new project.
2-Right click on the project name and choose Add New Class
3-Name the class tBackgroundWorker.
4-Imports System.ComponentModel
5-Serialize this ToolboxBitmap with follow by the class tBackgroundWorker.Usen _ if necessary.

Namespace AFRICTEK

_
Public Class BackgroundWorker : Inherits System.ComponentModel.Component
Private _CancelPending As Boolean = False
Private _ReportsProgress As Boolean = False
Private _SupportsCancellation As Boolean = False

Public Event DoWork As DoWorkEventHandler

Public Event ProgressChanged As ProgressChangedEventHandler

Public Event RunWorkerCompleted As RunWorkerCompletedEventHandler

Private Sub ProcessDelegate(ByVal delegateToProcess As System.Delegate, ByVal ParamArray args As Object())
If delegateToProcess Is Nothing Then
Exit Sub
End If

Dim delegates As System.Delegate() = delegateToProcess.GetInvocationList
For Each handler As System.Delegate In delegates
InvokeDelegate(handler, args)
Next
End Sub

Private Sub InvokeDelegate(ByVal delegateToInvoke As System.Delegate, ByVal args As Object())

Dim synchronizer As System.ComponentModel.ISynchronizeInvoke = Nothing
If GetType(System.ComponentModel.ISynchronizeInvoke).IsInstanceOfType(delegateToInvoke.Target) Then
synchronizer = DirectCast(delegateToInvoke.Target, System.ComponentModel.ISynchronizeInvoke)
End If

If Not (synchronizer Is Nothing) Then ' A windows Form object
If synchronizer.InvokeRequired = False Then
delegateToInvoke.DynamicInvoke(args)
Return
End If
Try
synchronizer.Invoke(delegateToInvoke, args)
Catch ex As Exception
End Try
Else ' Not a windows form object
delegateToInvoke.DynamicInvoke(args)
End If

End Sub

Private Sub AsyncOperationCompleted(ByVal asyncResult As IAsyncResult)

Dim doWorkEventDelegate As DoWorkEventHandler = CType(CType(asyncResult, System.Runtime.Remoting.Messaging.AsyncResult).AsyncDelegate, DoWorkEventHandler)
Dim doWorkArgs As DoWorkEventArgs = CType(asyncResult.AsyncState, DoWorkEventArgs)
Dim result As Object = Nothing
Dim doWorkEventError As Exception = Nothing


Try
doWorkEventDelegate.EndInvoke(asyncResult)
result = doWorkArgs.Result
Catch ex As Exception
doWorkEventError = ex
End Try

Dim completedArgs As RunWorkerCompletedEventArgs
completedArgs = New RunWorkerCompletedEventArgs(result, doWorkEventError, doWorkArgs.Cancel)
OnRunWorkerCompleted(completedArgs)
End Sub

Protected Overridable Sub OnRunWorkerCompleted(ByVal completedArgs As RunWorkerCompletedEventArgs)
ProcessDelegate(RunWorkerCompletedEvent, Me, completedArgs)
End Sub

Public Overloads Sub RunWorkerAsync()
RunWorkerAsync(Nothing)
End Sub

Public Overloads Sub RunWorkerAsync(ByVal argument As Object)
Me._CancelPending = False
If Not (DoWorkEvent Is Nothing) Then
Dim args As DoWorkEventArgs
If argument Is Nothing Then
argument = New Object
End If
args = New DoWorkEventArgs(argument)
Dim callback As AsyncCallback
callback = AddressOf Me.AsyncOperationCompleted
DoWorkEvent.BeginInvoke(Me, args, callback, args)
End If
End Sub

Public Overloads Sub ReportProgress(ByVal percent As Integer)
Me.ReportProgress(percent, Nothing)
End Sub

Public Overloads Sub ReportProgress(ByVal percent As Integer, ByVal userState As Object)
If WorkerReportsProgress Then
Dim progressArgs As ProgressChangedEventArgs = New ProgressChangedEventArgs(percent, userState)
OnProgressChanged(progressArgs)
End If
End Sub

Protected Overridable Sub OnProgressChanged(ByVal progressArgs As ProgressChangedEventArgs)
ProcessDelegate(ProgressChangedEvent, Me, progressArgs)
End Sub

Public Sub CancelAsync()
If Me._SupportsCancellation = True Then
SyncLock Me
Me._CancelPending = True
End SyncLock
Else
Throw New System.InvalidOperationException("This BackgroundWorker states that it doesn't support cancellation. Modify WorkerSupportsCancellation to state that it does support cancellation.")
End If
End Sub

Public ReadOnly Property CancellationPending() As Boolean
Get
SyncLock Me
Return Me._CancelPending
End SyncLock
End Get
End Property

Public Property WorkerSupportsCancellation() As Boolean
Get
SyncLock Me
Return Me._SupportsCancellation
End SyncLock
End Get
Set(ByVal Value As Boolean)
SyncLock Me
Me._SupportsCancellation = Value
End SyncLock
End Set
End Property

Public Property WorkerReportsProgress() As Boolean
Get
SyncLock Me
Return Me._ReportsProgress
End SyncLock
End Get
Set(ByVal Value As Boolean)
SyncLock Me
Me._ReportsProgress = Value
End SyncLock
End Set
End Property

End Class

Public Class DoWorkEventArgs : Inherits System.ComponentModel.CancelEventArgs

Private _Result As Object

Public Property Result() As Object
Get
Return Me._Result
End Get
Set(ByVal Value As Object)
Me._Result = Value
End Set
End Property

Public ReadOnly Argument As Object

Public Sub New(ByVal argument As Object)
Me.Argument = argument
End Sub

End Class

Public Class ProgressChangedEventArgs : Inherits EventArgs

Public ReadOnly ProgressPercentage As Integer
Public ReadOnly userState As Object

Public Sub New(ByVal percentage As Integer, ByVal userState As Object)
Me.ProgressPercentage = percentage
Me.userState = userState
End Sub

End Class

Public Class AsyncCompletedEventArgs : Inherits EventArgs

Public ReadOnly [Error] As Exception = Nothing
Public ReadOnly Cancelled As Boolean
Public ReadOnly UserState As Object

Public Sub New(ByVal runException As Exception, ByVal cancel As Boolean, ByVal userState As Object)
Me.Error = runException
Me.Cancelled = cancel
Me.UserState = userState
End Sub

Protected Sub RaiseExceptionIfNecessary()
If Me.Cancelled = True Then
Throw New System.InvalidOperationException("Operation has been cancelled.")
End If
If Not Me.Error Is Nothing Then
Throw New InvalidCastException
End If
End Sub

End Class

Public Class RunWorkerCompletedEventArgs : Inherits AsyncCompletedEventArgs

Public ReadOnly Property Result() As Object
Get
Me.RaiseExceptionIfNecessary()
Return Me.UserState
End Get
End Property

Public Sub New(ByVal result As Object, ByVal runException As Exception, ByVal cancel As Boolean)
MyBase.New(runException, cancel, result)
End Sub

End Class

Public Delegate Sub DoWorkEventHandler(ByVal sender As Object, ByVal e As DoWorkEventArgs)

Public Delegate Sub ProgressChangedEventHandler(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)

Public Delegate Sub RunWorkerCompletedEventHandler(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)

End Namespace

1 comment:

Anonymous said...

How would you get the results from this call back to the main program?

About Me

My photo
Raleigh, NC, United States
I am a software developer based in Raleigh,NC,USA.I design softwares and systems ;i also do consulting for companies worldwide.I program with these languages:VB.NET 2003/2005/2008;C#;Java(fun),SQL(200,2005,2008);ASP.NET 2.0/3.5;ASP.NET AJAX;ASP.NET MVC;JavaScript;JQuery;Windows Workflow Foundation;Web Services.I have 4 years + in programming.