C# 多个异步方法的异常处理
如果调用两个异步方法,每个都会抛出异常,该如何处理呢 ? 在下面的示例中,第一个 ThrowAfter 方法被调用,2s 后抛出异常(含消息 first)。该方法结束后,另一个 ThrowAfter 方法也被调用,1s 后也抛出异常。事实并非如此,因为对第一个 ThrowAfter 方法的调用已经抛出了异常,try 块内的代码没有继续调用第二个 ThrowAfter 方法,而是在 catch 块内对第一个异常进行处理。
代码如下:
private static async void StartTwoTasks()
{
try
{
await ThrowAfter(2000, "first");
await ThrowAfter(1000, "second"); // the second call is not invoked
// because the first method throws
// an exception
}
catch (Exception ex)
{
Console.WriteLine($"handled {ex.Message}");
}
}
现在,并行调用这两个 ThrowAfter 方法。第一个 ThrowAfter 方法 2s 后抛出异常,1s 后第二个 ThrowAfter 方法也抛出异常。使用 Task.WhenAll,不管任务是否抛出异常,都会等到两个任务完成。因此,等待 2s 后, Task.WhenAll 结束,异常被 catch 语句捕获到。但是,只能看见传递给 WhenAll 方法的第一个任务的异常信息,没有显示先抛出异常的任务(第二个任务),但该任务也在列表中:
private async static void StartTwoTasksParallel()
{
try
{
Task tl = ThrowAfter(2000, "first");
Task t2 = ThrowAfter(1000, "second");
await Task.WhenAll(tl, t2);
}
catch (Exception ex)
{
// just display the exception information of the first task
// that is awaited within whenAll
Console.WriteLine(S"handled {ex.Message}");
}
}
有一种方式可以获取所有任务的异常信息,就是在 try 块外声明任务变量 t1 和t2,使它们可以在 catch 块内访问。在这里,可以使用 IsFaulted 属性检查任务的状态,以确认它们是否为出错状态。若出现异常,IsFaulted 属性会返回true。可以使用 Task 类的 Exception.InnerException 访问异常信息本身。
评论