异步WebApi ActionFilterAttribute。异步模块或处理程序,而异步操作仍然悬而未决

问题描述:

完成我明白等待的任务(一个awaitable)完成等待。 但我对这实际上意味着什么感到困惑。异步WebApi ActionFilterAttribute。异步模块或处理程序,而异步操作仍然悬而未决

工作的代码:

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    if (actionExecutedContext.Response.Content != null) 
    { 
     var responseContent = await actionExecutedContext.Response.Content.ReadAsStringAsync(); 
     DoSomething(responseContent); 
    } 
} 

的代码确实工作:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    if (actionExecutedContext.Response.Content != null) 
    { 
     var responseContent = actionExecutedContext.Response.Content.ReadAsStringAsync().ContinueWith(
     task => 
     { 
      DoSomething(task.Result); 
     }); 
    } 
} 

显然错误消息异步模块或处理程序完成,而异步操作仍在进行中。告诉我,没有等待异步调用完成,而是继续“主”线程。我期望线程继续,但不在当前的方法。我认为线程将返回到asp.net堆栈做一些其他的工作,并返回一次等待asyncOperation()操作完成。

我使用的是等待在其他地方太 - (例如等待Web服务响应) - 我没有碰到类似问题的任何地方。我想知道为什么IActionFilterAttribute行为有所不同。事实上,我的Web服务调用可能比读取字符串中的响应内容更长。

有人请赐教吗?我有这种感觉,我不理解这个概念。

+0

动作过滤器(MVC的一部分,而不是WebAPI)不支持异步操作。如果您需要异步操作筛选器,请尝试使用消息处理程序。哦,并[在这里投票](http://aspnet.codeplex.com/workitem/9582)。 – 2013-03-19 15:19:25

+0

这是一个WebAPI问题,我使用正确的ActionFilterAttribute(System.Web.Http ...) - 你是说它应该工作? :) – lapsus 2013-03-19 15:32:16

+0

我明白了。在这种情况下,您可能需要定义自己的'AsyncActionFilterAttribute'并实现'IActionFilter.ExecuteActionFilterAsync'。 – 2013-03-19 15:37:12

添加异步代码返回void是危险的,几乎从来没有你真正想做的事情的方法。请参阅What's the difference between returning void and returning a Task?

相反,您需要重写/实现返回任务的方法。在这种情况下,ActionFilterAttribute隐藏了IHttpActionFilter提供的任务,因此您需要实现IActionFilter(ExecuteActionFilterAsync)。如果你想使用你的代码作为属性,只要确保你也从Attribute类派生。

例如:

public class AsyncActionFilterAttribute : Attribute, IActionFilter 
{ 
    public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
    { 
     HttpResponseMessage response = await continuation(); 
     DoSomething(response); 
     return response; 
    } 
} 

,而不是实施

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 

你必须实现OnActionExecuted方法的异步版本如下:

public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) 

这样,您就可以使用等待内部的方法和行为将如你所料。

希望这会有所帮助。