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
object.AggregateException
The
object has the AggregateException
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
method to run the Task.Run
()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 theAggregateException
thrown by the asynchronous operation executed by aTask
. - Use the
AggregateException.Handle()
method to handle exceptions.