赶上未处理的异步异常异常、未处理

2023-09-02 10:49:28 作者:Preference (偏爱)

当一个异步方法,该方法是在等待抛出一个异常,异常存储的地方,并把它扔延迟。在一个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.

如何从抛出prevent例外异步殃及的使用方法?

How can I prevent exceptions thrown from an async method from bringing down the application?

编辑:

Appearantly我所描述的问题,是因为我有无效 异步的方法。见注释。

Appearantly the issue I'm describing is because I have void async methods. See comments.

推荐答案

异步启动方法,它抓住了当前的同步内容。一种方法来解决这个问题是要创建自己的同步上下文捕捉异常。

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);
        }
    }
}

上面,你可以把你的异常处理逻辑。

In the catch above you can put your exception handling logic.

其次,每一个线程( 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());

完整例如:

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");
    }
}