我已经阅读了很多关于如何处理TPL中的异常但却不太了解的内容。
让我们看看这个示例代码:
var task1 = new Task(() => { throw new Exception("Throw 1"); });
var task2 = task1.ContinueWith(t => Console.WriteLine("Catch 1:{0}", t.Exception.Message),
TaskContinuationOptions.OnlyOnFaulted);
var task3 = task2.ContinueWith(t => Console.WriteLine("Continuation"));
task1.Start();
try {
task1.Wait();
}
catch (Exception ex) {
Console.WriteLine("Wait Exception: {0}", ex.Message);
}
我希望打印
Catch 1
Continuation
但是我得到了
Catch 1
Continuation
Wait Exception
这意味着当任务完成并且任务终结器最终将拆除应用程序时,异常仍被视为未处理。
如何在延续中处理异常,以便终结器不会抛出?同时我希望任务保持在故障状态,因此将任务包装在try / catch中不会工作
背景是我想实现指定here的异步事件模式,但有错误处理。我的完整代码看起来像这样
public IAsyncResult Begin(AsyncCallback callback, object state, Action action) {
var task1 = new Task(action);
var task2 = task1.ContinueWith(t => HandleException(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
if (callback != null) {
var task3 = task2.ContinueWith(t => callback(t),
TaskScheduler.FromCurrentSynchronizationContext());
var task4 = task3.ContinueWith(t => HandleException(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
}
task1.Start();
return task;
}
答案 0 :(得分:3)
你等待失败的任务,如果你仔细阅读documentation on Task.Wait,你会发现在这种情况下等待将重新抛出异常。
但是,如果你等待task3
,一切都应该按预期工作。
当然你应该牢记这一点:
当您使用OnlyOnFaulted选项时,保证了 前提中的异常属性不为null。你可以用它 捕获异常的属性,看看引起了哪个异常 任务到错。如果您不访问Exception属性,则 异常将无法处理。此外,如果您尝试访问结果 已被取消或出现故障的任务的属性,一个新的 异常将被提出。
(参考here)
最后又是How to handle exceptions thrown by tasks
的另一个好消息来源我希望这会有所帮助。