异步方法中抛出的异常未被捕获 - 为什么?

Lor*_*eno 1 .net c# asynchronous exception async-await

我很难理解 async/await 在各种非快乐路径情况下如何工作。例如,我有以下代码:

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

        private static void Do()
        {
            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                Console.WriteLine($"Unobserved Exception : {e.Exception.Message}");
                e.SetObserved();
            };
            
            try
            {                
                ThrowsAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Caught in try/catch  : {ex.Message}");
            }
        }

        private static async Task ThrowsAsync()
        {    
            Console.WriteLine("Throwing");
            throw new Exception("FAILURE");
        }
    }
Run Code Online (Sandbox Code Playgroud)

有两件事我不明白:

  1. ThrowsAsync方法是异步的,但是,它不包含任何await. 我假设在这种情况下该方法将像“正常”同步方法一样执行。然而,它抛出的异常永远不会被catch块捕获。
  2. 为了以某种方式捕获异常,我添加了TaskScheduler.UnobservedTaskException. 然而,它永远不会被执行。这是为什么?

我知道如果我等待,异常就会被捕获ThrowsAsync。不过,我正在尝试更好地了解它的工作原理。

我正在使用 .NET 5 和基于 Linux 的操作系统运行该代码。

Gur*_*ron 5

  1. 正如Stephen Cleary 的博客文章中所描述的,方法的状态机将从代码中捕获异常并将其放置在返回的任务上,即方法调用不会抛出异常,如果有结果async,您将能够捕获异常。await

  2. 至于TaskScheduler.UnobservedTaskException- 查看这个答案并确保在Release模式下运行代码。