BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Parallel and Asynchronous
.NET 4.0+

Exceptions and Parallel Loops

The sixth part of the Parallel Programming in .NET tutorial is the last instalment that examines the parallel loops. This article discusses how exceptions are thrown by code within a parallel loop and how they can be handled.

Catching Aggregated Exceptions

For the first demonstration we'll create a parallel loop that throws an exception. As we know that the exception will be wrapped within an AggregateException, we'll only catch AggregrateExceptions. The For loop below iterates through the values between -10 and 9. Each value is used as the divisor in a simple arithmetic operation. When the value is zero a division by zero error occurs and an exception is thrown.

NB: When you run the sample code, Visual Studio may break on the division by zero exception to allow debugging. If it does, press F5 to continue execution. You can avoid the problem by pressing Ctrl-F5 to run the program without debugging.

try
{
    Parallel.For(-10, 10, i =>
    {
        Console.WriteLine("100/{0}={1}", i, 100 / i);
    });
}
catch (AggregateException ex)
{
    Console.WriteLine(ex.Message);
}

/* OUTPUT

100/-10=-10
100/-5=-20
100/-9=-11
100/-6=-16
100/-2=-50
100/-1=-100
100/1=100
100/2=50
100/3=33
100/4=25
100/6=16
100/7=14
100/8=12
100/9=11
100/5=20
100/-8=-12
100/-7=-14
100/-4=-25
100/-3=-33
One or more errors occurred.

*/

The results shown in the above comments were generated on a quad-core processor. You can see that at some point in the process the division by zero exception was encountered and, after the loop stopped, the AggregateException was caught and its Message property outputted. The message is simple, indicating that the AggregateException contains one or more inner exceptions. NB: If we had attempted to catch a DivideByZeroException the exception would have been unhandled.

It is impossible to look at the above results and understand when the exception actually occurred. In a sequential loop we could assume that it was during the last processed iteration but in a parallel loop this may be incorrect. To understand what is actually happening, we can add an extra line to the code that tells us when we are about to divide by zero.

The sample below is modified to show a message just before the exception:

try
{
    Parallel.For(-10, 10, i =>
    {
        if (i == 0) Console.WriteLine("About to divide by zero.");
        Console.WriteLine("100/{0}={1}", i, 100 / i);
    });
}
catch (AggregateException ex)
{
    Console.WriteLine(ex.Message);
}

/* OUTPUT

100/-10=-10
100/5=20
About to divide by zero.
100/-5=-20
100/-4=-25
100/-3=-33
100/-2=-50
100/-1=-100
100/1=100
100/2=50
100/3=33
100/4=25
100/8=12
100/9=11
100/-6=-16
100/-9=-11
100/-8=-12
100/-7=-14
100/6=16
100/7=14
One or more errors occurred.

*/

With the new message we can see that the exception happened very early in the process, after only two calculation results had been shown. The remaining calculations happened after the initial exception in previously scheduled loop iterations. You should always consider this possibility when writing parallel loop code.

7 September 2011