在ActionFilterAttribute上的OnActionExecutedAsync中等待
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在ActionFilterAttribute上的OnActionExecutedAsync中等待相关的知识,希望对你有一定的参考价值。
我在WebApi项目中难以覆盖OnActionExecutedAsync
的ActionFilterAttribute
方法。到目前为止,我有以下c#代码
public class MyFilter : ActionFilterAttribute
{
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionContext, CancellationToken cancellationToken)
{
var response = await MyAsyncMethod();
if(response.SomeProperty)
DoThing();
}
}
但是,在调试代码时,对await方法的响应永远不会返回。对于任何异步方法都是如此,因为我已经测试了一些我知道在我的代码库中工作的异步方法。我也尝试了无效的方法,以及使用.Wait()
和.Result
都有相同的问题。
var response = MyAsyncMethod().Result;
await MyVoidAsyncMethod();
MyVoidAsyncMethod().Wait(cancellationToken);
所以我认为问题在于等待OnActionExecutedAsync方法中的任何方法。
我注意到我可以在没有问题的情况下等待基本方法。
await base.OnActionExecutedAsync(actionContext, cancellationToken);
如何在OnActionExecutedAsync
方法中调用异步方法?
更新示例显示纯粹等待的方法
由于通过确保链中的所有方法都在等待,我提出了评论中的一个解决方案,我添加了一个示例,该示例仅显示仍然导致问题的等待方法。
public class MyFilter : ActionFilterAttribute
{
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionContext, CancellationToken cancellationToken)
{
await base.OnActionExecutedAsync(actionContext, cancellationToken);
await DefinitelyAllAsync();
}
private async Task DefinitelyAllAsync()
{
var request = WebRequest.Create("http://www.stackoverflow.com");
var response = await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null) as HttpWebResponse;
Debug.Assert(response?.StatusCode == HttpStatusCode.OK);
}
}
这永远不会到达Debug.Assert
。
问题是,在较早时刻作用于请求的另一个过滤器未正确处理异步。在下面的示例中,AuthFilter
将在它的生命周期中比ActionFilter
更早地处理请求,并且如果它没有正确实现异步,那么当线程在请求生命周期中稍后点击其他过滤器时,线程将遇到异步问题。我的错误是假设ActionFilter
在它自己的线程上运行,因为它是我的代码的入口点。以下代码显示了正确实现await
运算符的两个过滤器。
的Global.asax.cs
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Filters.Add(new AuthFilter());
GlobalConfiguration.Configuration.Filters.Add(new ActionFilter());
}
AuthFilter.cs
public class AuthFilter : IAuthorizationFilter
{
public bool AllowMultiple => false;
public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
// incorrect use of async in this Filter will break async in future filters
return await continuation();
}
}
ActionFilter.cs
public class ActionFilter : ActionFilterAttribute
{
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionContext, CancellationToken cancellationToken)
{
await base.OnActionExecutedAsync(actionContext, cancellationToken);
await GetStackoverflow();
}
private async Task GetStackoverflow()
{
var request = WebRequest.Create("http://www.stackoverflow.com");
var response = await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null) as HttpWebResponse;
// this debug is unreachable if a past filter has implemented async incorrectly
Debug.Assert(response?.StatusCode == HttpStatusCode.OK);
}
}
以上是关于在ActionFilterAttribute上的OnActionExecutedAsync中等待的主要内容,如果未能解决你的问题,请参考以下文章
POST JSON 到 ActionFilterAttribute
ActionFilterAttribute:何时使用 OnActionExecuting 与 OnActionExecutingAsync?
是否为每个操作实例化了 ActionFilterAttribute?