I have a problem with exception handling and parallel tasks.
The code shown below starts 2 tasks and waits for them to finish. My problem is, that in case a task throws an exception, the catch handler is never reached.
List<Task> tasks = new List<Task>(); try { tasks.Add(Task.Factory.StartNew(TaskMethod1)); tasks.Add(Task.Factory.StartNew(TaskMethod2)); var arr = tasks.ToArray(); Task.WaitAll(arr); } catch (AggregateException e) { // do something }
However when I use the following code to wait for the tasks with a timeout, the exception is caught.
while(!Task.WaitAll(arr,100));
I seem to be missing something, as the documentation for WaitAll
describes my first attempt to be the correct one. Please help me in understanding why it is not working.
If Bar throws an exception, it will be thrown right at the point where you call it. However, if the Task that Bar returns wraps an exception, what happens depends on your version of . NET runtime - for .
WaitAll(Task[], TimeSpan)Waits for all of the provided cancellable Task objects to complete execution within a specified time interval.
Exceptions are propagated when you use one of the static or instance Task. Wait methods, and you handle them by enclosing the call in a try / catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.
The Task. WaitAll blocks the current thread until all other tasks have completed execution. The Task. WhenAll method is used to create a task that will complete if and only if all the other tasks have completed.
Can't reproduce this - it works fine for me:
using System; using System.Threading; using System.Threading.Tasks; class Test { static void Main() { Task t1 = Task.Factory.StartNew(() => Thread.Sleep(1000)); Task t2 = Task.Factory.StartNew(() => { Thread.Sleep(500); throw new Exception("Oops"); }); try { Task.WaitAll(t1, t2); Console.WriteLine("All done"); } catch (AggregateException) { Console.WriteLine("Something went wrong"); } } }
That prints "Something went wrong" just as I'd expect.
Is it possible that one of your tasks isn't finished? WaitAll
really does wait for all the tasks to complete, even if some have already failed.
Here's how I solved the problem, as alluded to in the comments on my answer/question (above):
The caller catches any exceptions raised by the tasks being coordinated by the barrier, and signals the other tasks with a forced cancellation:
CancellationTokenSource cancelSignal = new CancellationTokenSource(); try { // do work List<Task> workerTasks = new List<Task>(); foreach (Worker w in someArray) { workerTasks.Add(w.DoAsyncWork(cancelSignal.Token); } while (!Task.WaitAll(workerTasks.ToArray(), 100, cancelSignal.Token)) ; } catch (Exception) { cancelSignal.Cancel(); throw; }
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