SoFunction
Updated on 2025-03-06

c# Exception handling in task-based asynchronous programming mode (TAP)

As mentioned earlierTask-based Asynchronous Programming Mode (TAP), but if the asynchronous method is called without waiting, then the traditional try/catch block in the thread calling the asynchronous method cannot be caught. Because the execution has been completed before an exception occurs in the asynchronous method execution.

1. Calling asynchronous methods without waiting

The ThrowAfter method throws an exception after a certain delay:

private async Task ThrowAfter(int ms,string message)
{
  await (ms);
  ("The asynchronous task will then throw an exception.");
  throw new Exception(message);
}

When the DontHandle method calls an asynchronous method, due to the lag, it cannot catch exceptions in the asynchronous method using try...catch....

public void DontHandle()
{
  try
  {
    ThrowAfter(200, "Exception thrown by an asynchronous method");
  }
  catch(Exception ex)
  {
    ();
  }
  ("Method for completion: DontHandle");
}

Note: The asynchronous method that returns void will not wait. Because the exception thrown from the async void method cannot be caught. Therefore, it is best to return a Task type asynchronous method.

2. Exception handling of asynchronous methods

A better way to deal with asynchronous method exceptions is to use the await keyword and put it in a try/catch statement.

public async void HandleOneError()
{
  ("HandleOneError method starts executing....");
  try
  {
    await ThrowAfter(2000, "Exception thrown by an asynchronous method");
  }
  catch (Exception ex)
  {
    ();
  }
  ("Method for completion: HandleOneError");
}

After calling the ThrowAfter method, HandleOneError releases the thread, but it maintains a reference to the task when the task is completed. When an asynchronous method throws an exception, the code inside the matching catch block will be called.

3. Exception handling of multiple asynchronous methods

If multiple asynchronous methods are called, multiple exceptions will be thrown, and there will be problems when catching the exception.

public async void StartTwoTasks()
{
  ("The StartTwoTasks method starts executing....");
  try
  {
    await ThrowAfter(2000, "first");//Execute this method first    await ThrowAfter(1000, "Second");//The first asynchronous method will not be executed after normal execution of the method  }
  catch(Exception ex)
  {
    ();
  }
  ("How to complete: StartTwoTasks");
}

In the StartTwoTasks method, two asynchronous methods are called. In theory, it is believed that when the first asynchronous method is executed and the exception is thrown, the second asynchronous method will be called and the exception will be thrown. But in fact, after the first asynchronous method throws an exception, it will be caught by the catch and the second asynchronous method will not be executed. Because in this type, it was explained in the article "Task-based Asynchronous Programming Mode (TAP)", this calling method is to wait for the first asynchronous method to be executed before the thread control of the calling function will be called, and multiple asynchronous methods and so on. However, at that time, we used the WhenAll method in the Task class to wait for all tasks to be executed at the same time before executing the subsequent code.

public async void StartTwoTasksParallel()
{
  ("The StartTwoTasksParallel method starts executing....");
  try
  {
    Task t1 = ThrowAfter(2000, "first");//Execute this method first    Task t2 = ThrowAfter(1000, "Second");//The first asynchronous method will not be executed after the execution of the first asynchronous method    await (t1, t2);
  }
  catch (Exception ex)
  {
    ();
  }
  ("How to complete: StartTwoTasksParallel");
}

The StartTwoTasksParallel method uses the WhenAll method of the Task class to call two unrelated asynchronous methods in parallel. This method will wait until all tasks are finished before the call is finished. No matter whether any exception is thrown, it will not affect other tasks. However, this method will only catch the first exception (the task that throws the exception first), and other exceptions will not be displayed.

There is a way to obtain exception information for all tasks, which is to declare task variables t1 and t2 outside the try block, so that these two variables can be accessed within the catch block. The IsFaulted property of the task is detected in the catch block to confirm the status of the task to determine whether an exception occurs, and then access the exception information itself through the Task class.

4. Use AggregateException information

The method returns a Task result variable. The catch statement will only catch the first exception in all asynchronous tasks, but the Task type result variable returned by the method will contain exceptions that appear in all tasks. The Exception property of the external result task is an AggregateException type. You only need to traverse the InnerExceptions property of the Exception in the result task.

public async void ShowAggregatedException()
{
  ("ShowAggregatedException method starts executing....");
  Task taskResult = null;
  try
  {
    Task t1 = ThrowAfter(2000, "first");//Execute this method first    Task t2 = ThrowAfter(1000, "second");//The first asynchronous method will not be executed after the execution of the first asynchronous method    Task t3 = ThrowAfter(1500, "third");//The first asynchronous method will not be executed after the execution of the first asynchronous method    await (taskResult = (t1, t2, t3));
  }
  catch (Exception ex)
  {
    ("handle {0}",);
    foreach (Exception ex1 in )
    {
      ("Inner exception {0}", );
    }
  }
  ("Method for completion: ShowAggregatedException");
}

The above is the detailed content of exception handling in c# task-based asynchronous programming mode (TAP). For more information about c# asynchronous programming, please pay attention to my other related articles!