异步编程基础——async Task方法的异常处理
问题
异常处理对所有设计来说都是至关重要的一环。针对成功情况的设计实现起来简单,但只有把失败情况也处理得当,才算设计正确,幸运的是,async Task方法针对异常的处理也是直接了当的。
解决方案
异常可以通过简单的try/catch来捕获,就像处理同步代码一样:
async Task ThrowExceptionAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
throw new InvalidOperationException("Test");
}
async Task TestAsync()
{
try
{
await ThrowExceptionAsync();
}
catch(InvalidOperationException)
{
}
}
async Task方法引发的异常被放置在返回的Task中,只有在等待返回的Task时,他们才会触发。
async Task ThrowExceptionAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
throw new InvalidOperationException("Test");
}
async Task TestAsync()
{
//从方法中抛出的异常被置于任务中
Task task=ThrowExceptionAsync();
try
{
//在等待时,异常再次触发
await task;
}
catch(InvalidOperationException)
{
//在此处正确捕捉异常
}
}
讨论
当异常从async Task方法中抛出时,他会被捕捉并放置在在返回的Task中,由于async void 方法并没有用来放置异常的Task,因此这些方法的行为有错不同。
在对出错的Task加以await时,该任务的第一个异常会被再次抛出。
在大多数情况下,代码应将异常从其调用的异步方法上开始传播,其必行之事只是await从异步方法中返回的任务而已,而异常便会自然地传播。
在某些情况下,比如Task.WhenAll,一个Task可能有多个异常,而await只会再次抛出第一个