Task.WhenAny和Unobserved Exceptions
假设我有三个任务, a
, b
和c
。 这三个都保证在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); }
您可能希望在生产应用程序中包含日志记录。