【问题标题】:How do I catch in C# an exception from an asynchronous method that is awaited?如何在 C# 中捕获来自等待的异步方法的异常?
【发布时间】:2012-10-27 08:24:16
【问题描述】:

我基本上想知道在 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"); });
    }
}

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

编辑: 结果发现异常被捕获,出于技术原因,我只是在终端关闭之前没有注意到“异常捕获”消息。无论如何,Jon Skeet 的回答对我理解await 和异常处理非常有价值。

【问题讨论】:

  • 你是说这行不通?
  • 当我运行你的代码时,我看到“异常被捕获”。
  • 它不会被我抓住。我再检查一下。
  • @jishi 查看我编辑的问题,它确实被抓住了。
  • @spender 你说得对,在我的情况下由于技术原因没有注意到它。

标签: c# .net asynchronous exception-handling async-await


【解决方案1】:

为await 表达式生成的代码将在与TestAsync 返回的Task 关联的TaskAwaiter 上调用GetResult()。

GetResult 会注意到任务出错,从任务中的AggregateException 获取first 异常,然后抛出该异常。

最终结果是您的 catch 块将捕获您的任务中引发的异常 - 但如果您等待一个具有 多个 异常的任务,除非您采取特殊措施,否则您只会看到第一个异常行动(对此有多种方法)。

由于您声称该异常实际上没有得到处理,因此您的代码中似乎存在与您所显示的内容不同的内容 - 因为您提供的代码肯定可以工作,并且对我有用。

【讨论】:

  • 谢谢,午饭后会详细说明。
  • 事实证明异常确实被捕获了,但是在我按下一个键结束程序之前,确认消息没有写到控制台。因此,我一开始并没有注意到该消息被打印出来。猜猜异步需要一些时间来适应:)
  • 非常感谢您解释如何使用 await 处理异常,这对我的理解非常有用。
猜你喜欢
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 2017-03-23
相关资源
最近更新 更多