我的控制台应用使用System.ComponentModel.BackgroundWorker
进行线程处理:
System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
backgroundWorker.DoWork += (sender, e) =>
ReportStatus(worker, status, result, e);
backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker.RunWorkerAsync(worker);
正如您所看到的,我在RunWorkerAsync中传递“worker”作为参数。
我想要实现的是,如果ReportStatus方法中有异常,我需要相同的“worker”对象,以便我可以执行一些操作(调用服务来通知工作者异常)
private void ReportStatus(Worker worker, Status status, WorkResult result,System.ComponentModel.DoWorkEventArgs arg)
{
var proxy = new PreparationServiceProxy(new NetTcpBinding(), new EndpointAddress(PreparationEngineState.ServiceAddress));
try
{
proxy.ReportStatus(worker, status, result);
proxy.Close();
}
catch (Exception)
{
arg.Result = worker;
proxy.Abort();
throw;
}
}
在我的异常块中(我不确定这是否是正确的方法!)我将worker分配给Result,以便在执行RunWorkerCompleted方法(backgroundWorker1_RunWorkerCompleted)时可以返回同一个worker:
private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
Worker worker = e.Result as Worker; // At this point I get an exception!
}
}
答案 0 :(得分:2)
这是因为你重新抛出异常。 BackgroundWorker
将DoWork
处理程序未处理的异常视为异常,并在获得Result
值时将其重新抛回另一个线程。
如果您不希望这样做,请删除throw
处理程序中catch中的DoWork
。
如果你将worker对象传递给BackgroundWorker
,为什么不使用你在包含对Result
的调用的异常处理程序中或在测试{{1}的块中传入的内容}}? e.g:
Error
答案 1 :(得分:2)
如果发生错误,.NET不会认为异步操作可能会产生一些结果。这就是为什么你会以其他方式传递它。
我建议实现自定义异常类:
public class WorkerException:ApplicationException
{
public WorkerException(Worker worker,Exception innerException):base(null,innerException)
{ Worker = worker; }
public Worker Worker
{
get;
set;
}
}
相应地包装你的异常:
private void ReportStatus(Worker worker, Status status, WorkResult result,System.ComponentModel.DoWorkEventArgs arg)
{
var proxy = new PreparationServiceProxy(new NetTcpBinding(), new EndpointAddress(PreparationEngineState.ServiceAddress));
try
{
proxy.ReportStatus(worker, status, result);
proxy.Close();
}
catch (Exception exception)
{
arg.Result = worker;
proxy.Abort();
throw new WorkerException(worker,exception);
}
}
在这种情况下,您将能够检索异常工作者,将错误强制转换为WorkerException:
private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Error is WorkerException)
{
Worker worker = ((WorkerException)e.Error).Worker; // At this point I get an exception!
}
}
答案 2 :(得分:0)
RunWorkerCompletedEventArgs
包含UserState
属性,我认为该属性应该是您传递给RunWorkerAsync
方法的同一对象的引用。 (它也应该在DoWorkEventArgs
中作为Argument
属性。)
您需要进行试验以确认此UserState
是正确的对象(强制转换为as Worker
),并且即使DoWork
处理程序引发异常,它也是有效的,但是我认为这可能就是你要找的东西。