异步编程基础——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只会再次抛出第一个