从异步中捕获未处理的异常 [英] Catch unhandled exceptions from async

查看:18
本文介绍了从异步中捕获未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当等待的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆