如何在多个函数调用之间检查BackgroundWorker取消

时间:2013-12-13 15:50:16

标签: vb.net backgroundworker function-call cancellation

我有一个BackgrounWorker从名为ExcelOutput的自定义类中调用vairous方法。以下功能有效,但不允许我检查取消。

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

为此,我设置了上面列出的每个方法来检查错误(使用Try/Catch),如果有错误,我设置bw.WorkerSupportsCancellation = True bw.CancelAsync()方法(您会注意到我在启动Me实例时传递了ExcelOutput,这样就可以了。)

这个方法有效,但为了完全实现它,我必须将每个调用包装在If块中,这样会使代码非常长且难以阅读(每个调用从1行到6行) -

If bw.CancellationPending = True Then
    e.Cancel = True
    Exit Sub
Else
    CurrentRow = Excel.OutputGroup("General", UserDump.lstGeneralHeaders, UserDump.lstGeneralData, 4)
End If

有没有更好的方法来做到这一点,既可以保持代码简短,又可以提供取消检查的功能?感谢。

更新

感谢下面的回答,这里是我正在使用的确切bw_DoWork()方法,它完全符合我的要求 -

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

1 个答案:

答案 0 :(得分:2)

在DoWork事件中没有使用try / catch的“常见”规则。例外情况是您要处置或清理对象。如果发生错误,它将在RunWorkerCompleted事件(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

话虽如此,您可以尝试在While Loop中完成工作,并在每个周期后检查取消。

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
相关问题