当等待的async
方法抛出异常时,异常会存储在某处并且会延迟抛出异常。在WinForms或WPF应用程序中,它使用SynchronizationContext.Current
发布抛出异常。但是,在例如一个控制台应用程序,它会在线程池上抛出异常并关闭应用程序。
如何防止async
方法引发的异常关闭应用程序?
修改
我正在描述的问题显然是因为我有void
async
方法。见评论。
答案 0 :(得分:19)
如何防止异步方法引发的异常导致应用程序崩溃?
遵循以下最佳做法:
async
方法都应返回Task
或Task<T>
,除非 返回void
(例如,事件处理程序)。await
从Task
方法返回所有async
。你不想这样做的唯一原因是你不再关心操作的结果(例如,你取消它后)。async void
事件处理程序中捕获异常,那么在事件处理程序中捕获它 - 就像你是同步代码一样。您可能会发现我的async
/ await
intro post很有帮助;我还介绍了其他几个最佳实践。
答案 1 :(得分:10)
启动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
方法的每个线程([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");
}
}