【问题标题】:How to catch exception in an async method?如何在异步方法中捕获异常?
【发布时间】:2021-10-18 18:16:14
【问题描述】:

我正在学习异步和等待。下面的“catch”没有捕捉到 DoTask 中抛出的异常。假设 DoTask 是我无法更改的第三方方法,我该如何修复它以便 catch 子句捕获异常?

private static async Task DoTask()
{
    await Task.Delay(10000);
    throw new Exception("Exception!");
}


public static void Main(string[] args)
{
    try
    {
        Task.Run(async () => await DoTask());
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    Console.WriteLine("End");
    Console.ReadKey();
}

【问题讨论】:

标签: c# async-await


【解决方案1】:

这个简化怎么样:

public static async Task Main(string[] args)
{
    try
    {
        await DoTask();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    Console.WriteLine("End");
    Console.ReadKey();
}

【讨论】:

    【解决方案2】:

    只有在等待任务时才能捕获AggregateException。因此,当您不等待 Task.Run 时,执行线程会移出 try 块,现在您无法捕获异常以防万一发生。至于 AggregateException - 它是一个包含一个或多个异常的包装器,您可以在其属性 InnerExceptions 中访问这些异常。我建议阅读这篇精彩的文章,深入了解这个主题和 C# 中的线程:http://www.albahari.com/threading/part5.aspx#_Working_with_AggregateException

    你也可以看看这个:https://www.youtube.com/watch?v=J0mcYVxJEl0(26:00 左右是答案,但总的来说是一场精彩的演讲!)

    【讨论】:

    • 很抱歉,请您详细说明一下 - 我不能……
    • 当然!因此,当您不等待 Task.Run 时,正在执行的线程只是移出 try 块,现在您无法捕获异常以防万一发生。至于 AggregateException - 它是一个包含一个或多个异常的包装器,您可以在其属性 InnerExceptions 中访问这些异常。我建议阅读这篇精彩的文章,深入了解这个主题和 C# 中的线程:albahari.com/threading/…
    • 另请参阅:youtube.com/watch?v=J0mcYVxJEl0(26:00 谈论尝试和等待)
    • @YomB - 不要在 cmets 中详细说明。请在您的答案中添加详细信息。
    【解决方案3】:

    我解决了 - 我需要等待任务完成。在我添加“Task.WaitAll(task);”后,它捕获了异常。

    private static async Task DoTask()
    {
        await Task.Delay(10000);
        throw new Exception("Exception!");
    }
    
    
    public static void Main(string[] args)
    {
        try
        {
            Task task = DoTask();
            Task.WaitAll(task);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.InnerException.Message);
        }
    
        Console.WriteLine("End");
        Console.ReadKey();
    }
    

    【讨论】:

    • 既然可以Task task = DoTask();,为什么还要Task task = Task.Run(async () => await DoTask());
    • 是的——我真傻。我从某处复制了代码行“Task.Run(async () => await DoTask())”。我没有意识到这只是比两行更短的方法:“Task task = DoTask(); Task.WaitAll(task);”
    猜你喜欢
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 2016-08-26
    • 2021-10-09
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    相关资源
    最近更新 更多