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).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);
}
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:
Task.Wait
/WaitAll
/WaitAny
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With