任务和任务.WaitAll具有超时exception处理

当使用Task.WaitAll等待任务并在WaitAll超时时指定超时时,我还必须单独观察任何未完成的任务(例如通过注册延续)?

这个post让我觉得答案是肯定的,但我还没有找到其他证实这一点的东西。

var random = new Random(); var tasks = Enumerable.Range(0, 10).Select((i) => Task.Factory.StartNew(() => { // Sleep 5-15 seconds Thread.Sleep(random.Next(5000, 15000)); throw new Exception("Some exception."); } )).ToArray(); try { // Wait for 10 seconds Task.WaitAll(tasks, 10000); } catch (AggregateException) { // Swallow } // Check to see how many tasks were unfinished tasks.Where(t => !t.IsCompleted).Count().Dump("Unfinished count: "); // Is this neccessary to avoid exceptions being thrown on the finalizer? foreach (Task task in tasks) { task.ContinueWith(t => t.Exception, TaskContinuationOptions.OnlyOnFaulted); } 

为了避免崩溃终结器,您必须观察Task主体抛出的exception。 要观察Taskexception,您必须执行以下操作之一:

  1. 访问exception属性
  2. 调用Task.Wait / WaitAll / WaitAny
  3. 注册仅在任务出现故障时才运行的延续

你做了什么绝对是必要的,以避免崩溃终结者。

使用LINQPad v4.31进行测试表明答案是肯定的,因为如果您注释掉foreach,则会为每个未完成的任务获得未处理的exception对话框。

我相信我明白为什么会这样,但是如果有人想通过各种手段对这种行为进行更加技术性的解释那就去吧。