I have a BackgrounWorker
that calls vairous methods from a custom class called ExcelOutput
. The below function works, but it does not allow me to check for cancellation.
Private Sub bw_DoWork(ByVal sender As Object,
ByVal e As DoWorkEventArgs)
Dim UserDump As New CurrentUserDumpInfo(Me.MainForm.ConfigForm) ' Create a new instance of the CurrentUserDumpInfo
Dim Excel As New ExcelOutput(Me) ' Create a new instance of the ExcelOutput
Dim FirstRow As Integer = 4 ' The row on which the output should start
Dim CurrentRow As Integer ' The currnet row on which the output shoud continue
'** Prepare the CurrentUserDumpInfo and the ExcelOutput *'
Call UserDump.prepare()
Call Excel.Prepare()
CurrentRow = Excel.OutputGroup("General", UserDump.lstGeneralHeaders, UserDump.lstGeneralData, FirstRow)
CurrentRow = Excel.OutputGroup("Address", UserDump.lstAddressHeaders, UserDump.lstAddressData, CurrentRow + 2)
Call Excel.AutofitContents(4, CurrentRow)
Call Excel.AlignCells(4, CurrentRow)
Call Excel.StyleWorksheet()
Call Excel.MakeSafeCopy()
Call Excel.LockWorksheet()
Call Excel.Finish(UserDump.CurrentUser.FullName)
End Sub
To do this, I've set each methods listed above to check for errors (using Try/Catch
), and if there is an error, I set call the bw.WorkerSupportsCancellation = True
bw.CancelAsync()
method (you'll notice I pass Me
when initiating the ExcelOutput
instance, making this possible).
This method works, but to implement it fully I have to wrap every call in an If
block like so, making the code very long and difficult to read (each call goes from 1 line to 6 lines) -
If bw.CancellationPending = True Then
e.Cancel = True
Exit Sub
Else
CurrentRow = Excel.OutputGroup("General", UserDump.lstGeneralHeaders, UserDump.lstGeneralData, 4)
End If
Is there a better way to do this, that will both keep the code short and sweat but offer the functionality of the cancellation check? Thanks.
Thanks to the answer below, here is the exact bw_DoWork()
method that I am now using, which achieves exactly what I was looking for -
Private Sub bw_DoWork(ByVal sender As Object,
ByVal e As DoWorkEventArgs)
Dim UserDump As New CurrentUserDumpInfo(Me.MainForm.ConfigForm) ' Create a new instance of the CurrentUserDumpInfo
Dim Excel As New ExcelOutput(Me) ' Create a new instance of the ExcelOutput
Dim FirstRow As Integer = 4 ' The row on which the output should start
Dim CurrentRow As Integer ' The currnet row on which the output shoud continue
Dim Counter As Integer = 0
While Not bw.CancellationPending = True
Select Case Counter
Case 0 : Call UserDump.prepare() : Exit Select ' Prepare the CurrentUserDumpInfo object ready for use
Case 1 : Call Excel.Prepare() : Exit Select ' Prepare the ExcelOutput object ready for use
Case 2 : CurrentRow = Excel.OutputGroup("General", UserDump.lstGeneralHeaders, UserDump.lstGeneralData, FirstRow) : Exit Select
Case 3 : CurrentRow = Excel.OutputGroup("Address", UserDump.lstAddressHeaders, UserDump.lstAddressData, CurrentRow + 2) : Exit Select
Case 4 : CurrentRow = Excel.OutputGroup("Account", UserDump.lstAccountHeaders, UserDump.lstAccountData, CurrentRow + 2) : Exit Select
Case 5 : CurrentRow = Excel.OutputGroup("Profile", UserDump.lstProfileHeaders, UserDump.lstProfileData, CurrentRow + 2) : Exit Select
Case 6 : Call Excel.AutofitContents(4, CurrentRow) : Exit Select
Case 7 : Call Excel.AlignCells(4, CurrentRow) : Exit Select
Case 8 : Call Excel.StyleWorksheet() : Exit Select
Case 9 : Call Excel.MakeSafeCopy() : Exit Select
Case 10 : Call Excel.LockWorksheet() : Exit Select
Case 11 : Call Excel.Finish(UserDump.CurrentUser.FullName) : Exit Select
Case Else : Exit While
End Select
Counter += 1
End While
'** Check to see if the BackgroundWorker should be cancelled *'
If bw.CancellationPending = True Then e.Cancel = True
End Sub
There's a "common" rule not to use try/catch in a DoWork event. The exception is if you want to dispose or clean up objects. If an error occurs it will be available in the RunWorkerCompleted
event (e.Error).
Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
Dim obj As IDisposable = Nothing
Dim [error] As Exception = Nothing
Try
obj = New Control()
Throw New Exception("Simulated exception")
Catch ex As Exception
[error] = ex
Finally
If (Not obj Is Nothing) Then
obj.Dispose()
obj = Nothing
End If
End Try
If (Not [error] Is Nothing) Then
Throw [error]
End If
End Sub
With that being said, you can try to do the work in a While Loop
and check for cancellation after each cycle.
Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
Dim worker As BackgroundWorker = DirectCast(sender, BackgroundWorker)
Dim num As Integer = Nothing
Dim obj As IDisposable = Nothing
Dim [error] As Exception = Nothing
Try
'TDOD: obj = New IDisposable ()
num = 0
While (Not e.Cancel)
Select Case num
Case 0
'Do somthing
Exit Select
Case 1
'Do somthing
Exit Select
Case 2
'Do somthing
Exit Select
Case Else
Exit While
End Select
num += 1
e.Cancel = worker.CancellationPending
End While
Catch ex As Exception
[error] = ex
Finally
If (Not obj Is Nothing) Then
obj.Dispose()
obj = Nothing
End If
End Try
If (Not [error] Is Nothing) Then
Throw [error]
ElseIf (Not e.Cancel) Then
'TODO: e.Result = Nothing
End If
End Sub