Async WebApi ActionFilterAttribute.在异步操作仍处于挂起状态时完成异步模块或处理程序

lap*_*sus 9 actionfilterattribute async-await asp.net-web-api

我理解等待完成任务(等待).但我对这实际意味着什么感到困惑.

该代码工作:

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

该代码的工作:

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

显然错误消息异步模块或处理程序在异步操作仍处于挂起状态时完成.告诉我,没有等待异步调用完成,而是"主"线程继续.我期望线程继续但不在当前方法中.我认为线程将返回到asp.net堆栈执行其他工作并在await asyncOperation()操作完成后返回.

我也在其他地方使用等待 - (例如等待Web服务响应) - 我没有在任何地方遇到过类似的问题.我想知道为什么IActionFilterAttribute的行为不同.实际上,我的Web服务调用可能比将响应内容读入字符串要长.

有人可以赐教吗?我感觉我不理解这个概念.

dma*_*son 9

将异步代码添加到返回void的方法是危险的,几乎不是你真正想做的事情.看看返回void和返回任务有什么区别?.

相反,您需要覆盖/实现返回任务的方法.在这种情况下,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;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

而不是实施

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
Run Code Online (Sandbox Code Playgroud)

您必须OnActionExecuted按如下方式实现方法的异步版本:

public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
Run Code Online (Sandbox Code Playgroud)

这样您就可以在方法中使用 await 并且行为将如您所愿。

希望这可以帮助。