gpt4 book ai didi

c# - 为什么我无法捕获返回类型为 void 的异步函数中的异常?

转载 作者:行者123 更新时间:2023-12-05 09:05:07 25 4
gpt4 key购买 nike

static void Main(string[] args) {
try {
var a = MyMethodAsync();
a.Wait(); // calling Wait throw an AggregateException
}
catch (Exception e) {
Console.WriteLine("Catch");
}

Console.ReadLine();
}

static async Task<String> MyMethodAsync() {
String s = await TestThrowException();
return s;
}

static Task<String> TestThrowException() {
return Task.Run(() => {
throw new DivideByZeroException();
return "placeholder"; // return statement is needed for the compilier to work correctly
});
}

上面的代码有效,Main 方法中的 catch block 可以捕获 AggregateException 异常(源自 TestThrowException 并转换为 AggregateException) .

但是如果我有这样的代码:

static void Main(string[] args) {
try {
MyMethodAsync();
}
catch (Exception e) {
Console.WriteLine("Catch");
}
Console.ReadLine();
}

static async void MyMethodAsync() {
await TestThrowException();
}

static Task<String> TestThrowException() {
return Task.Run(() => {
throw new DivideByZeroException();
return "placeholder";
}

那么Main方法中的catch block 就捕获不到任何异常,这是为什么呢?

最佳答案

任何时候你有 async void,你基本上打破了正确指示完成 失败的能力;它可以报告失败的唯一方式是异常立即发生并且在任何未完成的await之前发生 - 即同步发生。在您的情况下,Task.Run 保证这是同步的,因此任何关于结果和失败的知识:都将丢失。

从根本上说,永远不要写async void(除非您绝对必须这样做,例如在事件处理程序中)。除了上述问题之外,它已知一些 SynchronizationContext 实现(尤其是遗留的 ASP.NET 实现)的复杂性,这意味着只需调用一个 async void 方法足以使您的应用程序崩溃(至少在假设上;同步上下文警告更适用于库作者而不是应用程序作者,因为库作者无法选择应用程序执行环境)。

移除async void。如果你想返回“nothing”,那么你应该使用 async Taskasync ValueTask 作为签名:

static async Task MyMethodAsync() {
await TestThrowException();
}

(也许也可以简化为)

static Task MyMethodAsync()
=> TestThrowException();

和:

static async Task Main(string[] args) {
try {
await MyMethodAsync();
}
catch (Exception e) {
Console.WriteLine("Catch");
}
Console.ReadLine();
}

关于c# - 为什么我无法捕获返回类型为 void 的异步函数中的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67704898/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com