如何从等待的异步方法中捕获C#异常?

akn*_*ds1 5 .net c# asynchronous exception-handling async-await

我基本上想知道我应该如何在C#中捕获通过await关键字等待的异步方法的异常.例如,考虑以下小型控制台程序,其中最重要的是包含一个名为的方法AwaitSync.AwaitSync调用TestAsync,返回一个在执行时抛出异常的Task.我尝试捕获异常AwaitAsync,但它没有处理.

class Program
{
    static void Main(string[] args)
    {
        AwaitAsync();
        Console.ReadKey();
    }

    static async Task AwaitAsync()
    {
        try
        {
            await TestAsync();
        }
        catch (Exception)
        {
            Console.WriteLine("Exception caught");
        }
    }

    static Task TestAsync()
    {
        return Task.Factory.StartNew(() => { throw new Exception("Test"); });
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该如何从返回的Task中捕获异常TestAsync?虽然这个例子是一个控制台程序,但我的真实生活问题是在ASP.NET MVC/Web API的上下文中.

编辑: 事实证明异常被抓住了,由于技术原因我在终端关闭之前没有注意到"异常捕获"消息.无论如何,Jon Skeet的回答对我理解await和异常处理非常有价值.

Jon*_*eet 10

await表达式生成的代码将调用与返回GetResult()TaskAwaiter关联TaskTestAsync.

GetResult会注意到任务出现故障,从任务中获取第一个异常AggregateException,并抛出该异常.

最终结果是你的catch块将捕获你的任务中抛出的异常 - 但是如果你等待一个有多个异常的任务,你只会看到第一个,除非你采取特殊的行动(有各种方法).

当你声称异常实际上没有处理时,你的代码中似乎有一些东西,而不是你所展示的内容 - 因为你给出的代码肯定会起作用,对我来说也是如此.