在async void操作中抛出时,未处理的异常会导致Web API服务崩溃

时间:2013-02-15 05:06:29

标签: .net exception asp.net-web-api

根据documentation HttpResponseException自动由Web API处理,而Web API应该将HttpResponseMessage返回给具有相应HttpStatusCode的客户端。它通常有用......

但是,如果我们从标有HttpResponseException的操作中抛出async,那么这只是不起作用而HttpResponseException只会崩溃整个服务,例如“用户未处理异常代码“消息。添加自定义异常过滤器无法解决问题,因为Web API无法捕获HttpResponseException消息。

更新1 我进一步调查并发现,只要将await修饰符添加到操作中,此操作中的每个未处理的异常都会导致Web API服务崩溃。并且不涉及ExceptionFilterAttributes,Web API只是不执行它们。您甚至不必从异步代码中抛出异常,只需将async添加到操作中就可以使每个异常完全无法处理。

这里可以正常工作,异常过滤器可以捕获异常:

public void Test()
{
    throw new Exception("Hello");
}

这会导致服务崩溃:

public async void Test()
{
    throw new Exception("Hello");
}

更新2 好吧,如果我们将void改为某种真实类型,看起来一切正常:

public async Task<int> Test()
{
    throw new Exception("Hello");
}

因此,看起来async void中的未处理异常导致服务崩溃,但async Task<SomeType>运行良好,异常过滤器会捕获除HttpResponseException以外的所有内容,并且HttpResponseException由Web正确处理API。

看起来我刚才和自己说过话,但是找出为什么async void行动中的例外无法正确处理会很有意思?

1 个答案:

答案 0 :(得分:4)

避免async void的原因之一是这些方法进行错误处理的方式。

async void方法旨在用作事件处理程序。 所有其他async方法应为async Taskasync Task<T>async等效的同步void - 返回方法为async Task async void

返回任务对象的

async方法会将异常放在该任务对象上。 async void方法没有任务对象,因此它们通过在SynchronizationContext方法开始执行时处于活动状态的async void上提升异常来处理异常。这模拟了事件处理程序的行为。