10

我了解 await等待任务(可等待)完成。但我对这实际上意味着什么感到困惑。

不起作用的代码:

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() 操作完成后返回。

我也在其他地方使用 await ——(例如等待 Web 服务响应)——而且我在任何地方都没有遇到类似的问题。我想知道为什么 IActionFilterAttribute 行为不同。事实上,我的 Web 服务调用可能比将响应内容读入字符串花费的时间更长。

有人可以启发我吗?我感觉我没有理解这个概念。

4

2 回答 2

11

将异步代码添加到返回 void 的方法是危险的,而且几乎永远不会是您真正想要做的事情。请参阅返回 void 和返回 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;
    }
}
于 2013-07-12T17:43:55.130 回答
7

而不是实施

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)

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

public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)

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

希望这可以帮助。

于 2015-05-28T10:00:47.000 回答