2013-12-13 28 views
1

我有一個BackgrounWorker調用從自定義類稱爲ExcelOutput vairous方法。下面的功能起作用,但它不允許我檢查取消。如何檢查BackgroundWorker之間取消多個函數調用之間的取消

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()方法(你會發現我當啓動ExcelOutput實例時,通過Me,使這成爲可能)。

此方法的工作,但要完全實現它,我必須包裝每次調用在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 
+0

它可能是一個錯字,但'WorkerSupportsCancellation'屬性應該只在設計時設置。你應該做的是設置'CancellationPending'屬性。 –

+0

好點,這是一個錯字。我實際上調用了'bw.CancelAsync()'方法,我相信這是設置'CancellationPending'的方法。我很快就會糾正...... –

回答

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 
+0

使用'While'循環與'Select Case'結合使用的好處。這就是我所實施的,它完美的工作。 –

+0

好!順便說一句,如果你想要更少的行:'情況0:調用UserDump.prepare():退出選擇' –

+0

我已經使用'情況0:調用UserDump.prepare()'。我可以假設'退出選擇'將停止檢查未來的匹配,因此可能節省執行時間(與PHP'break'相同)? –