捕获异步回调中抛出的exception
我有一个方法,它采用一个回调参数异步执行,但catch块似乎没有捕获同步调用抛出的任何exception( 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); }
有没有办法捕获新线程抛出的exception并将其发送到原始线程? 另外,这是处理异步exception的“正确”方法吗? 我编写了我的代码,因此可以像这样调用(假设exception问题已修复):
try { target.Submit(file, (response) => { // do stuff }); } catch (Exception ex) { // catch stuff }
但有没有更合适或更优雅的方式来做到这一点?
这不是一个“最佳实践”解决方案,但我认为这应该是一个简单的解决方案。
而不是将委托定义为
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字段,并相应地执行操作。
如果您的目标是.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中exception处理的更多信息,请访问: http : //msdn.microsoft.com/en-us/library/dd997415.aspx
总之,没有。
当你调用submitDelegate.BeginInvoke
,它会生成新线程,返回并立即退出你的try / catch块(当新线程在后台运行时)。
但是,您可以捕获所有未处理的exception,如下所示:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);
这将捕获应用程序域中的所有内容(但不仅仅是您的异步方法)。