我有一个方法,它使一个回调参数异步执行,但是catch块似乎没有捕获同步调用抛出的任何异常(this.Submit
指的是同步方法)。
public void Submit(FileInfo file, AnswerHandler callback)
{
SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit);
submitDelegate.BeginInvoke(file, (IAsyncResult ar) =>
{
string result = submitDelegate.EndInvoke(ar);
callback(result);
}, null);
}
有没有办法捕获新线程抛出的异常并将其发送到原始线程?另外,这是处理异步异常的“正确”方法吗?我编写了我的代码,因此可以像这样调用(假设异常问题已修复):
try
{
target.Submit(file, (response) =>
{
// do stuff
});
}
catch (Exception ex)
{
// catch stuff
}
但是有更合适或更优雅的方法吗?
答案 0 :(得分:9)
如果您的目标是.NET 4.0,则可以使用新的任务并行库,并观察Task
对象的Exception
属性。
public Task Submit(FileInfo file)
{
return Task.Factory.StartNew(() => DoSomething(file));
}
private void DoSomething(FileInfo file)
{
throw new Exception();
}
然后像这样使用它:
Submit(myFileInfo).ContinueWith(task =>
{
// Check task.Exception for any exceptions.
// Do stuff with task.Result
});
其中DoSomething
是您要异步调用的方法,而传递给ContinueWith
的代理是您的回调。
有关TPL中异常处理的更多信息,请访问:http://msdn.microsoft.com/en-us/library/dd997415.aspx
答案 1 :(得分:8)
这不是“最佳实践”解决方案,但我认为这是一个应该有效的简单解决方案。
而不是将委托定义为
private delegate string SubmitFileDelegate(FileInfo file);
将其定义为
private delegate SubmitFileResult SubmitFileDelegate(FileInfo file);
并按如下方式定义SubmitFileResult:
public class SubmitFileResult
{
public string Result;
public Exception Exception;
}
然后,实际进行文件提交的方法(未在问题中显示)应该像这样定义:
private static SubmitFileResult Submit(FileInfo file)
{
try
{
var submissionResult = ComplexSubmitFileMethod();
return new SubmitFileResult { Result = submissionResult };
}
catch (Exception ex)
{
return new SubmitFileResult {Exception = ex, Result = "ERROR"};
}
}
这样,您将检查结果对象,看它是否设置了Result或Exception字段,并相应地采取行动。
答案 2 :(得分:3)
简而言之,没有。
当你调用submitDelegate.BeginInvoke
时,它会生成新线程,返回并立即退出你的try / catch块(当新线程在后台运行时)。
然而,您可以捕获所有未处理的异常,如下所示:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);
这将捕获应用程序域中的所有内容(但不仅仅是异步方法)。