Software Development

Handling AggregateExceptions

I’ve written a couple of posts (see also) about how the AggregateException plays its part in exception handling in parallel systems. However, it has another trick up its sleeve when it comes to handling exceptions.

AggregateException has a Handle method that takes a delegate of Func<Exception, bool> i.e. It takes an Exception as a parameter and returns a bool. The return value indicates whether the function handled the exception or not.

Here is an example program that shows what how it works.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            DoWork();
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("Handle Remaining Exceptions");
            foreach(Exception ex in aex.InnerExceptions)
            {
                Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        Console.ReadLine();
    }

    private static void DoWork()
    {
        const int numTasks = 20;
        Task[] tasks = new Task[numTasks];
        for (int i = 0; i < numTasks; i++)
            tasks[i] = Task.Factory.StartNew(PerformTask);

        Thread.Sleep(2500);

        try
        {
            Task.WaitAll(tasks);
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("AggregateException.Handle...");
            aex.Handle(ex => HandleException(ex));
            Console.WriteLine("Finished handling exceptions."); // This never shows
        }
    }

    public static bool HandleException(Exception ex)
    {
        if (ex is OddException)
        {
            Console.WriteLine("Handling: {0}", ex.Message);
            return true;
        }

        Console.WriteLine("Not handling: {0}", ex.Message);
        return false;
    }

    public static void PerformTask()
    {
        int? id = Task.CurrentId;
        Console.WriteLine("Performing Task {0}", id);

        if (id.Value % 13 == 0)
            throw new TriskaidekaException("Mwaaahaahaahaahaaaaaaaa!");

        if (id.Value % 2 == 1)
            throw new OddException("The task ("+id+") is distinctly odd.");
    }
}

The program starts 20 tasks (DoWork). Each task (PerformTask) simply outputs a line to the console to say what it’s id is and then throws an exception depending on some condition. There are two types of exception that it can throw.

Back in the main thread (DoWork) a Sleep statement gives the tasks a chance to get going (and hopefully complete). During this time, the tasks get the opportunity to output the following.

Performing Task 1
Performing Task 2
Performing Task 4
Performing Task 3
Performing Task 5
Performing Task 8
Performing Task 9
Performing Task 10
Performing Task 12
Performing Task 13
Performing Task 6
Performing Task 14
Performing Task 7
Performing Task 16
Performing Task 17
Performing Task 18
Performing Task 15
Performing Task 11
Performing Task 19
Performing Task 20

Then the Task.WaitAll statement is called which will potentially throw an AggregateException (in fact it will with 10 InnerExceptions).

Since the Task.WaitAll call is wrapped in a try/catch the AggregateException is caught. We output a message to say the exceptions are being handled. The AggregateException.Handle method calls the method given (HandleException) once for each of the InnerExceptions.

AggregateException.Handle...

The HandleException method either handles the exception (in which case it returns true) or it doesn’t (so returning false). In each case it also writes to the console to say what it has done. That console output looks like this:

Handling: The task (19) is distinctly odd.
Handling: The task (17) is distinctly odd.
Handling: The task (15) is distinctly odd.
Not handling: Mwaaahaahaahaahaaaaaaaa!
Handling: The task (11) is distinctly odd.
Handling: The task (9) is distinctly odd.
Handling: The task (7) is distinctly odd.
Handling: The task (5) is distinctly odd.
Handling: The task (3) is distinctly odd.
Handling: The task (1) is distinctly odd.

The AggregateException.Handle method then checks to see if any of the exceptions remain unhandled. If there are still unhandled exceptions then it rethrows. Since there is one remaining exception that is unhandled the line of code after the call to Handle is never called.

The try/catch block in the Main method catches AggregateException and just loops over the remaining exceptions to show what was left unhandled.

Handle Remaining Exceptions
TriskaidekaException: Mwaaahaahaahaahaaaaaaaa!

See also

One thought on “Handling AggregateExceptions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s