如何使用异步等待处理多个异常
Posted
技术标签:
【中文标题】如何使用异步等待处理多个异常【英文标题】:How to handle multiple exceptions with async await 【发布时间】:2015-09-01 20:46:49 【问题描述】:我遵循 Microsoft 在此处指定的模式。 https://msdn.microsoft.com/en-us/library/hh191443.aspx
本文介绍了如何使用 await 开发异步代码。但是,他们没有谈论在 await 返回之前出现异常时会发生什么。
在下面的示例中,外部异常结束了父线程,并且任务没有线程可以返回。我该如何处理这种情况?
class Program
private static void Main(string[] args)
CallAsync();
Console.ReadKey();
public static async void CallAsync()
var task = CallExceptionAsync();
ThrowException("Outside");
await task;
public static Task CallExceptionAsync()
return Task.Run(() =>
ThrowException("Inside");
);
public static void ThrowException(string msg)
throw new Exception(msg);
【问题讨论】:
【参考方案1】:您必须准备好处理可能已渗透回主线程的异常,方法是用 try/catch 包围该调用。在这种情况下,您应该收到一个 AggregateException
,它包含您启动的异步线程中的一个或多个异常。
【讨论】:
我有点误读了你的例子。我所说的对于您正在启动的第二个线程是正确的,但是您也在主线程级别引发了异常。你想说啥?如果您没有针对该主线程异常的 catch 块,它将被终止(或被更高层的其他代码捕获)。你是问如果第一个线程在它之前终止,第二个线程会发生什么? 我的例子是一个愚蠢的例子。我的实际代码更复杂,我能够在这里复制相同的行为。在我的原始代码中,我正在调用 Web 服务,同时也保存到数据库中。两者都抛出异常。我可以在这里复制一个不太复杂的例子。它是否在 main 中与 .wait() 无关。行为仍然是一样的 我在这里抛出另一个问题来评论:我的理解是如果主线程终止,它的所有子线程都会同时终止。这是真的吗? @Anish 你指的“行为”是什么? 这篇帖子似乎表明,如果主线程是 main() 方法所在的地方,则主线程(和进程)及其所有“子”线程将被终止,但如果它不是,所有的“子”线程都会继续执行。 ***.com/questions/4666628/…【参考方案2】:这正是您不应该使用async void
的原因。在常规异步方法中,从方法主体抛出的异常被捕获并存储在返回的任务中。因为在async void
的情况下,调用者没有任务来观察异常导致进程停止。
所以,你应该返回一个任务,在Main
的情况下你可以和Task.Wait
同步阻塞:
private static void Main()
CallAsync().Wait();
public static async Task CallAsync()
var task = CallExceptionAsync();
ThrowException("Outside");
await task;
使用Task.Wait
阻塞不是真正的应用程序的合适解决方案,因为它可能导致涉及SynchronizationContext
的死锁。在这种情况下,您可以使用 Stephen Cleary 的 AsyncContext
。
【讨论】:
你能再深入一点 AsyncContext 吗? @Anish 它为没有任何控制台应用程序提供SynchronizationContext
(与 UI 应用程序不同)。但这不是重点。关键是要避免async void
。 async void
仅适用于事件处理程序。以上是关于如何使用异步等待处理多个异常的主要内容,如果未能解决你的问题,请参考以下文章