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:
- Access the exception property
- Call
Task.Wait
/WaitAll
/WaitAny
- 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.
精彩评论