如何在异步操作仍处于挂起状态时修复已完成的异步模块或处理程序

分享于2022年07月17日 asp.net-mvc asp.net-mvc-4 async-await c# 问答
【问题标题】:如何在异步操作仍处于挂起状态时修复已完成的异步模块或处理程序(How to fix asynchronous module or handler completed while an asynchronous operation was still pending)
【发布时间】:2022-01-27 07:26:31
【问题描述】:

我在访问控制器时拥有此自定义授权,但我不断收到以下错误消息:谁能帮我识别代码中的问题?

//Controller
[GlobalDataAuthorization]
public ActionResult Index()
{
     return View();
}

// Custom Authorization
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class GlobalDataAuthorization : AuthorizeAttribute
{
    public  async override void OnAuthorization(AuthorizationContext filterContext)
    {
        var authorizationBuilder = new AuthorizationBuilder();
        bool hasAccess = await authorizationBuilder.GetUserAccess();
        if (!hasAccess)
        {
            filterContext.Result = new RedirectResult("~/Home");
        }    
    }

}

检查用户访问的生成器类:

public interface IAuthorizationBuilder
{
    Task GetUserAccess();
}

public class AuthorizationBuilder : IAuthorizationBuilder
{
    public async Task GetUserAccess()
    {

        var authConfigsResponse = await GetAuthConfigurationsAsync(); //http request
        var allSupportedRoles =  SetUpAllSupportedRoles(authConfigsResponse);
        var supportedRoles = SetUpSupportedRoles(allSupportedRoles);
        var result = await CheckClaimsAsync(supportedRoles, allSupportedRoles);//http request
        return result;
    }
 }

  • async override void OnAuthorization 无效,您不能只采用同步方法并使其异步 - 调用者将无法等待它完成。

【解决方案1】:

ASP.NET (pre-Core) MVC 不支持异步过滤器。 ASP.NET Core MVC 确实支持异步过滤器。

假设您还没有准备好迁移到 Core(这是最终必要的解决方案),您需要执行某种同步异步反模式。我有一个您可以使用的 few hacks in an article I wrote

例如,阻塞线程池 hack 适用于大多数代码,尤其是在 ASP.NET 设置中:

public override void OnAuthorization(AuthorizationContext filterContext)
{
  var authorizationBuilder = new AuthorizationBuilder();
  bool hasAccess = Task.Run(() => authorizationBuilder.GetUserAccess()).GetAwaiter().GetResult();
  if (!hasAccess)
  {
    filterContext.Result = new RedirectResult("~/Home");
  }    
}