从异步中捕获未处理的异常 [英] Catch unhandled exceptions from async
问题描述
当等待的 async
方法抛出异常时,异常存储在某处并延迟抛出.在 WinForms 或 WPF 应用程序中,它使用 SynchronizationContext.Current
来发布异常的抛出.然而,在例如一个控制台应用程序,它在线程池上抛出异常并关闭应用程序.
When an async
method that is awaited upon throws an exception, the exception is stored somewhere and throwing it is delayed. In a WinForms or WPF application, it uses SynchronizationContext.Current
to post throwing of the exception. However, in e.g. a console application, it throws the exception on a thread pool and it brings down the application.
如何防止从 async
方法抛出的异常导致应用程序关闭?
How can I prevent exceptions thrown from an async
method from bringing down the application?
显然我描述的问题是因为我有 void
async
方法.查看评论.
Appearantly the issue I'm describing is because I have void
async
methods. See comments.
推荐答案
当 async
方法启动时,它会捕获当前的同步上下文.解决此问题的一种方法是创建您自己的同步上下文来捕获异常.
When the async
method is started, it captures the current synchronization context. A way to solve this issue is to create your own synchronization context which captures the exception.
这里的重点是同步上下文将回调发布到线程池,但周围有一个 try/catch:
The point here is that the synchronization context posts the callback to the thread pool, but with a try/catch around it:
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
中,您可以放置异常处理逻辑.
In the catch
above you can put your exception handling logic.
接下来,在每个要使用此机制执行 async
方法的线程(SynchronizationContext.Current
是 [ThreadStatic]
)上,您必须设置当前同步上下文:
Next, on every thread (SynchronizationContext.Current
is [ThreadStatic]
) where you want to execute async
methods with this mechanism, you must set the current synchronization context:
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");
}
}
这篇关于从异步中捕获未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!