Exception Handling in Parallel Task Library

Before reading this article I request that you read my previous article on Parallel Task that is a feature in .Net 4.0 so that you can get a better idea regarding Exception Handling in tasks.

Parallel Task in .Net 4.0

I am writing this article as requested by one of my friends on C# corner. When I talked regarding the parallel execution of tasks in my previous article, I didn't explain exception handling. I mean in parallel task execution, exception handling is important and behaves in a different manner.

Let us continue with the same example that I used in my earlier article of "A person digging in the ground". We knew that unhandled exceptions that are thrown by user code needs to be handled.

Let's consider the scenario and understand exception handling for it.

1. Exception handling for Single Task

Now, a person while digging the ground suddenly the tool got crashed and he must stop the further digging. Now it's easy to handle this kind of exception.

  1.  Task t = Task.Factory.StartNew(() => {  
  2.    try  
  3.    {  
  4.      Console.WriteLine("Digging is in progress");  
  5.      throw new Exception("Tool is crashed");  
  6.    }  
  7.    catch (Exception ae)  
  8.    {  
  9.         Console.WriteLine("Stop the work and notify others :" + ae.Message);  
  10.    } 
    });  
  11. t.Wait();  

In the code snippet above, as you can find I have handled the exception simply using an Exception object.

2. Exception handling for Nested Task

The previous one was pretty simple, right? But it is not the right way of using it. I will exlain later.

Now what if one person wants to do some other small task along with digging that is going on, like removing the stones. Suddenly something went wrong. Another point is while digging too there was some problem with the tool too. Now what to do to handle both the exception that is running in parallel?

rendom image

This task would be a child task for digging in the ground. Here there is a chance of getting exceptions in the Parent as well as the child task, in other words, multiple errors. And to propagate all the exceptions to the calling Thread, the Exception class is not capable of doing it. So the Task infrastructure wraps up all the exceptions into one object that is of type AggregateException. This is derived from the Exception class.

This class has an InnerExceptions property that can be enumerated to get all the exceptions while executing the Task and handling each of the Task exceptions differently. It can also be used to throw even single Exception.

image for exception

try catch example

The figure above shows the Exception. You can see I have used an Exception object in the catch block to handle the Exception.

Output

catch block to handle

Even though I have custom Exception message to be shown, still it is showing some other message. This is because an Exception object cannot handle Task related exceptions.

custom Exception message

Now check the preceding figure, the exception details are bubbling up to the Main Thread and getting wrapped up to a single AggregateException object.

Note: Your tasks may still continue to process even after exceptions are raised. That is something you need to handle.

Output

exceptions details

As you can see how I am able to enumerate through all exceptions.

3. Exception handling for Multiple Tasks completion

Let's consider a scenario where a person is digging in the ground and along with that the task of cleaning of the ground is continuing in parallel. And there is a problem (exception) in any of the tasks or both. And we have used the WaitAll() method to ensure both tasks are completed.

  1. try  
  2.     {  
  3.       Task t1 = Task.Factory.StartNew(() =>  
  4.       {  
  5.            for (int index = 0; index < 5; index++)  
  6.            {  
  7.                 Console.WriteLine("Digging completed for " + index + "mts. area ");  
  8.            }  
  9.            Task childtask = Task.Factory.StartNew(() =>  
  10.            {  
  11.               Console.WriteLine("Remove stones");   
  12.               throw new Exception("Something went wrong");   
  13.            }, TaskCreationOptions.AttachedToParent);  
  14.            throw new Exception("Tools crashed");  
  15.      });   
  16.      Task t2 = Task.Factory.StartNew(() =>  
  17.      {  
  18.         Console.WriteLine("Clean the area");  
  19.         for (int index = 0; index < 5; index++)  
  20.         {  
  21.            Console.WriteLine("Cleaning....");  
  22.         }  
  23.                     throw new Exception("Problem occured");  
  24.      });   
  25.      Task.WaitAll(t1, t2);  
  26.   }
      catch (AggregateException ae)  
  27.   {  
  28.      foreach (var item in ae.Flatten().InnerExceptions)  
  29.      {  
  30.        Console.WriteLine("Stop the work and notify others :" + item.Message);  
  31.      }  
  32. }  
Output

AggregateException output

As you can see in the output above, how all errors are thrown one by one by the AggregateException class.

Conclusion

I hope you like this article that explains about how to handle errors thrown in case of a Parallel Task, a feature of .Net 4.0. Please share your comments whether good or bad. Sharing is valuable no matter what :)

Reference

Exception Handling (Task Parallel Library)