Handling Exceptions in C# Task

Summary: in this tutorial, you’ll learn how to handle exceptions raised by the asynchronous operation executed by the Task objects.

Introduction to AggregateException

In general, when a Task encounters an exception, it will propagate the exception to the calling thread. If a Task contains nested tasks, any asynchronous operations performed within these tasks may also result in multiple exceptions being thrown.

To propagate all the exceptions to the calling thread, the Task wraps them in an AggregateException object.

The AggregateException object has the InnerExceptions property that contains all the original exceptions. The InnerExceptions is a read-only collection of the Exception instances.

To handle these exceptions, you can enumerate them through the InnerExceptions property of the AggregateException object using a foreach loop.

Alternatively, you can handle the original exceptions using the AggregateException.Handle method:

public void Handle (Func<Exception,bool> predicate);Code language: PHP (php)

It’s important to note that the Task will wrap any exceptions that occur within an AggregationException object, even if a single exception is raised.

Handling AggregateException example

The following program illustrates how to handle exceptions in an asynchronous operation executed by a task.

decimal Divide(decimal a, decimal b)
{
    Thread.Sleep(1000);

    return a / b;
}

try
{
    var task = Task.Run(() => Divide(10, 0));
    var result = task.Result;
}
catch (AggregateException ae)
{
    ae.Flatten().Handle(e =>
    {
        if (e is DivideByZeroException)
        {
            Console.WriteLine(e.Message);
            return true;
        }
        else
        {
            throw e;
        }
    });
}Code language: C# (cs)

How it works.

First, define a method Divide() that takes two decimal numbers and returns the result of dividing them after a delay of one second:

decimal Divide(decimal a, decimal b)
{
    Thread.Sleep(1000);

    return a / b;
}Code language: C# (cs)

Second, use the Task.Run() method to run the Divide() method asynchronously in a separate thread. Since we use the arguments 10 and 0, the Divide() method will throw a DivideByZeroException exception:

var task = Task.Run(() => Divide(10, 0));Code language: C# (cs)

Third, use the try…catch block to catch any exceptions thrown by the method. Since the asynchronous operation throws an AggregateException, we catch and handle it in the catch block.

In the exception handler, we use the Handle() method of the AggregateException class to handle each inner exception.

If the exception is DivideByZeroException, the program outputs the error message to the console. Otherwise, it rethrows the same exception.

When you run the program, you’ll see the following output:

Attempted to divide by zero.Code language: C# (cs)

Summary

  • Use the try...catch to catch the AggregateException thrown by the asynchronous operation executed by a Task.
  • Use the AggregateException.Handle() method to handle exceptions.
Was this tutorial helpful ?