开发者

Task and Task.WaitAll with timeout exception handling

When waiting for Tasks using Task.WaitAll and specifying a timeout if the WaitAll times out do I also have to separately observe any unfinished tasks (e.g. by registering a continuation)?

This thread leads me to think the answer is yes, but I haven't found anything else that confirms this.

var random = new Random();
var tasks = Enumerable.Range(0, 10).S开发者_开发技巧elect((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);
}


To avoid crashing the finalizer, you have to observe the exceptions thrown by the Task body. To observe a Task exception you have to do one of the following:

  1. Access the exception property
  2. Call Task.Wait/WaitAll/WaitAny
  3. Register a continuation that only run if the task faulted

What you did is definitely necessary to avoid crashing the finalizer.


Testing with LINQPad v4.31 indicates the answer is yes, since if you comment out the foreach you get an unhandled exception dialog for each unfinished task.

I believe I understand why this is at this point but if anybody wants to have a go at a more technical explanation of this behavior by all means go for it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜