Task.WhenAny和Unobserved Exceptions

假设我有三个任务, abc 。 这三个都保证在1到5秒之间的随机时间抛出exception。 然后我写下面的代码:

 await Task.WhenAny(a, b, c); 

这将最终从任何一个任务故障中抛出exception。 由于没有try...catch这里,这个例外会冒泡到我的代码中的其他地方。

剩下的两个任务抛出exception会发生什么? 是不是这些未被观察到的exception,这将导致整个过程被杀死? 这是否意味着使用WhenAny的唯一方法是在try...catch块中,然后在继续之前以某种方式观察剩余的两个任务?

后续行动:我希望将答案同时应用于.NET 4.5 .NET 4.0以及Async Targeting Pack(尽管在这种情况下显然使用了TaskEx.WhenAny )。

剩下的两个任务抛出exception会发生什么?

这些Task将在故障状态下完成。

是不是这些未被观察到的exception,这将导致整个过程被杀死?

不再。

在.NET 4.0中, Task析构函数会将其未观察到的exception传递给TaskScheduler.UnobservedTaskException ,如果未处理则会终止该进程。

在.NET 4.5中,此行为已更改 。 现在,未观察到的exception会传递给TaskScheduler.UnobservedTaskException ,但如果未处理则会被忽略。

是的,未观察到剩余的任务exception。 在.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); } 

您可能希望在生产应用程序中包含日志记录。