任务和任务.带有超时异常处理的WaitAll

本文关键字:任务 WaitAll 异常处理 超时 | 更新日期: 2023-09-27 18:06:06

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

这个线程让我认为答案是肯定的,但我还没有发现任何其他证实这一点。

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);
}

任务和任务.带有超时异常处理的WaitAll

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

  1. 访问异常属性
  2. 呼叫Task.Wait/WaitAll/WaitAny
  3. 注册一个只在任务出错时运行的延续

你所做的对于避免终结器崩溃是必要的。

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

我相信我明白为什么会这样,但是如果有人想尝试对这种行为进行更技术性的解释,请尽管去做。