当async
等待的方法抛出异常时,异常存储在某处并延迟抛出。在 WinForms 或 WPF 应用程序中,它用于SynchronizationContext.Current
发布异常的抛出。但是,例如在控制台应用程序中,它会在线程池中引发异常并关闭应用程序。
如何防止async
方法引发的异常导致应用程序崩溃?
编辑:
显然我所描述的问题是因为我有void
async
方法。看评论。
当async
等待的方法抛出异常时,异常存储在某处并延迟抛出。在 WinForms 或 WPF 应用程序中,它用于SynchronizationContext.Current
发布异常的抛出。但是,例如在控制台应用程序中,它会在线程池中引发异常并关闭应用程序。
如何防止async
方法引发的异常导致应用程序崩溃?
编辑:
显然我所描述的问题是因为我有void
async
方法。看评论。
如何防止异步方法引发的异常导致应用程序崩溃?
遵循以下最佳做法:
async
方法都应该返回Task
或者Task<T>
除非它们必须返回void
(例如,事件处理程序)。await
全部Task
从async
方法返回。您不想这样做的唯一原因是您不再关心操作的结果(例如,在您取消它之后)。async void
,则在事件处理程序中捕获它 - 就像这是同步代码时所做的那样。您可能会发现我的async
/await
介绍帖子很有帮助;我还介绍了其他几个最佳实践。
当该async
方法启动时,它会捕获当前的同步上下文。解决此问题的一种方法是创建自己的同步上下文来捕获异常。
这里的要点是同步上下文将回调发布到线程池,但它周围有一个 try/catch:
public class AsyncSynchronizationContext : SynchronizationContext
{
public override void Send(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
public override void Post(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
}
在catch
上面你可以放置你的异常处理逻辑。
接下来,在您希望使用此机制执行方法的每个线程 ( SynchronizationContext.Current
is ) 上,您必须设置当前同步上下文:[ThreadStatic]
async
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
完整的Main
例子:
class Program
{
static void Main(string[] args)
{
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
ExecuteAsyncMethod();
Console.ReadKey();
}
private static async void ExecuteAsyncMethod()
{
await AsyncMethod();
}
private static async Task AsyncMethod()
{
throw new Exception("Exception from async");
}
}