Backgroundworker:取消期间的例外情况

时间:2009-06-26 11:25:00

标签: c# multithreading exception backgroundworker

我有一个可以取消的后台工作人员。

当CancelPending变量变为true时,正常流程会自行中断(响应UI上的用户交互,调用worker.CancelAsynch()),抛出异常,因为如果那样(因为正常流程被中断,很多空引用异常都是抛出)

因此,当工作者返回时,我希望能够区分工作时抛出的异常 被取消(默默地忽略它们)从未取消工作时抛出的异常(向UI报告)。

我的代码如下(抱歉c#/ vb mix ...):

工人阶级:

Public Class ClassBaseGetObjectsWorker
    Inherits System.ComponentModel.BackgroundWorker


 Protected Overrides Sub OnDoWork(ByVal e As System.ComponentModel.DoWorkEventArgs)
        Try

            Dim cpt As Int16 = 0
            While cpt < 5
                System.Threading.Thread.Sleep(1000)
                cpt = cpt + 1
                If CheckForCancellation() Then
                    'Simulating exception due to cancel
                    Throw New Exception("Exception du to cancel !")
                End If
            End While

        Catch exc As Exception
            e.Cancel = Me.CancellationPending
            Throw exc
        End Try

    End Sub
End Class

回电:

void setObjSetCollWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    if (e.Cancelled) {
        resultLabel.Text += "Canceled";
        //e.Error is selently ignored
    }
    else {
        if (e.Error != null) {
            //Reporting errors arising during normal (uncanceled) flow
            throw e.Error.InnerException;
        }
        else {
            //Worker process finished without error or being canceled.
            updateUIAfterBackgroundJob();
        }
    }
}

然后,当我正在做worker.CancelAsynch()时,e.Cancelled在Completed回调中设置为false(这不是我的预期)。如果我在工作人员中评论“Trow exc”,如果我测试的话 再次,e.Cancelled正确设置为true。

那么,获取我想要的信息的最简洁方法是什么,即:我想知道当工作者处于cancelPending状态时是否抛出了在已完成的处理程序中弹出的异常。

(抱歉我的英语不好)

1 个答案:

答案 0 :(得分:0)

如果在OnDoWork()实现中构造代码的最佳方法是在检测到取消时抛出异常,请执行以下操作:

创建一个CancelException:

public class CancelException: Exception {}

当您检测到取消待处理时抛出此CancelException:

if(CheckForCancellation()) throw new CancelException();

在OnDoWork()方法代码中添加try-catch:

protected override void OnDoWork(DoWorkEventArgs e){
  try{
    //...
  }
  catch(CancelException){
    // silently return
    return;
  }
}

这样你的代码就会遵守BackgroundWorker-contract(当你检测到取消挂起时从OnDoWork()返回,而不是抛出异常),而且Canceled属性现在应该如你所愿