假设我有三个任务,a
,b
和c
。所有三个都保证在1到5秒之间的随机时间抛出异常。然后我写下面的代码:
await Task.WhenAny(a, b, c);
这最终将从任何一个任务故障中抛出异常。由于此处没有try...catch
,因此此异常会冒泡到我的代码中的其他位置。
当剩下的两个任务抛出异常时会发生什么?是不是这些未被观察到的异常,这将导致整个过程被杀死?这是否意味着使用WhenAny
的唯一方法是在try...catch
块内,然后在继续之前以某种方式观察剩余的两个任务?
后续行动:我希望将答案同时应用于.NET 4.5 和 .NET 4.0以及Async Targeting Pack(尽管明确使用{{1在那种情况下)。
答案 0 :(得分:23)
当剩下的两个任务抛出异常时会发生什么?
那些Task
将在故障状态下完成。
这些未被观察到的异常是否会导致整个过程被杀死?
不再。
在.NET 4.0中,Task
析构函数会将其未观察到的异常传递给TaskScheduler.UnobservedTaskException
,如果未处理则会终止该进程。
在.NET 4.5中,这是behavior was changed。现在,未观察到的异常传递给TaskScheduler.UnobservedTaskException
,但如果未处理则会被忽略。
答案 1 :(得分:5)
是的,未观察到剩余的任务异常。在.NET 4.5之前,您有义务观察它们(不确定.NET 4.5的情况如何,但它已经改变了。)
我经常给自己写一个辅助方法,用于完成这样的即发即弃任务:
public static void IgnoreUnobservedExceptions(this Task task)
{
if (task.IsCompleted)
{
if (task.IsFaulted)
{
var dummy = task.Exception;
}
return;
}
task.ContinueWith(t =>
{
var dummy = t.Exception;
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
您可能希望在生产应用中包含日志记录。