C# Backgroundworker:取消期间发生异常
我有一个背景工人,可以取消 当CancelPending变量变为true时,正常流中断自身(响应调用worker.CancelAsynch()的UI上的用户交互),会引发异常,因为如果这样(由于正常流中断,会引发大量null ref异常) 所以,当工作者返回时,我希望能够区分工作者返回时抛出的异常 已从未取消工作进程时引发的异常中取消(以静默方式忽略它们)(以向UI报告它们) 我的代码如下(很抱歉c#/vb混合使用…): 工人阶级:C# Backgroundworker:取消期间发生异常,c#,multithreading,exception,backgroundworker,C#,Multithreading,Exception,Backgroundworker,我有一个背景工人,可以取消 当CancelPending变量变为true时,正常流中断自身(响应调用worker.CancelAsynch()的UI上的用户交互),会引发异常,因为如果这样(由于正常流中断,会引发大量null ref异常) 所以,当工作者返回时,我希望能够区分工作者返回时抛出的异常 已从未取消工作进程时引发的异常中取消(以静默方式忽略它们)(以向UI报告它们) 我的代码如下(很抱歉c#/vb混合使用…): 工人阶级: Public Class ClassBaseGetObject
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
然后,当我执行worker.CancelAsynch()时,在完成的回调中将e.Cancelled设置为false(这不是我所期望的)。如果我在worker中注释掉“Trow exc”,如果我再次测试,e.Cancelled正确设置为true
获取我想要的信息的最干净的方法是什么,也就是说:我想知道当工作进程处于cancellationPending状态时,在完成的处理程序中弹出的异常是否被抛出?如果在OnDoWork()实现中构造代码的最佳方法是在检测到取消时抛出异常,请执行以下操作: 创建取消异常:
public class CancelException: Exception {}
检测到取消挂起时引发此CancelException:
if(CheckForCancellation()) throw new CancelException();
在OnDoWork()方法中的代码周围添加一个try catch:
这样,您的代码将遵守BackgroundWorker约定(即在检测到取消挂起时从OnDoWork()返回,而不是抛出异常),并且Cancelled属性现在应该如您所期望的那样,它是如何处理被取消的?worker与上面的模拟代码类似:它经历了几个级别的函数调用,如果CancellationPending(通过委托检查)变为true,则每个执行循环都将退出。考虑到流被中断且结果将被丢弃的事实,这些提前退出的循环和函数会导致“正常”的异常。为什么要问这个问题?一个不太好的选择是在我的BackgroundWorker派生类中添加一个公共成员“wascelected”,该类可以在OnDoWork catch块中设置为true(Me.wascelected=Me.CancellationPending)。然后可以在完成的回调中使用此成员。
if(CheckForCancellation()) throw new CancelException();
protected override void OnDoWork(DoWorkEventArgs e){
try{
//...
}
catch(CancelException){
// silently return
return;
}
}