来自基础控制器的异步方法调用 - 旧的 .net 项目

问题描述 投票:0回答:1

我继承了一个 .net 4.6.2 MVC 项目,该项目通过从基本控制器内部进行 API 调用来填充来自基本控制器的视图包。我需要确保在基本控制器发出 api 请求之前我有一个有效的访问令牌来执行此操作。 由于基本控制器返回 void,我在等待调用以确保我获得有效的访问令牌时遇到了一些问题,并且收到了

an asynchronous module or handler completed while an asynchronous operation was still pending.
错误。 我对如何继续感到有点困惑,在这种情况下,任何人都可以为我提供有关如何解决此问题的建议,或者可能是一个合理的重构,仍然实现我的目标,即不仅在我的控制器中而且在基础中拥有有效的访问令牌控制器。

我尝试过以下方法:

  var accessTokenProvider = new AccessTokenProvider();
  var task = accessTokenProvider.AcquireAccessTokenAsync(filterContext)
      .ConfigureAwait(false)
      .GetAwaiter();
  task.GetResult();

但这会导致初始加载时间非常长 - 有时会抛出 500 - 请求超时。 网络服务器未能在指定时间内响应。

asp.net asp.net-mvc asynchronous controller
1个回答
0
投票

这会导致初始加载时间非常长 - 有时会抛出 500 - 请求超时。网络服务器未能在指定时间内响应。

这可能是由于 ASP.NET pre-Core 应用程序中的“异步代码阻塞”造成的。链接是我的博客,我在其中详细解释了僵局。

因为基本控制器返回 void,我在等待调用以确保我获得有效的访问令牌时遇到了一些问题,并且收到了
an asynchronous module or handler completed while an asynchronous operation was still pending.

错误。


这是一个“安全网”异常,意味着代码不正确。在这种情况下,
它可能使用了

async void

,这是一个禁忌
在这种情况下,任何人都可以向我提供关于如何解决此问题的建议,或者可能是一个合理的重构,以仍然实现我的目标,即不仅在我的控制器中而且在基本控制器中拥有有效的访问令牌。

你最好的选择是

一路异步
。您的基本控制器中可能有一个新方法来获取访问令牌;将该方法设为

async Task 而不是 async void

,并确保在调用 API 之前对 
Task
 进行 
await
 处理。
另一种选择是使所有代码同步。理想情况下,您应该拥有(或编写)一个完全同步工作的 
AccessTokenProvider.AcquireAccessToken

方法(即,不会阻塞异步代码,这可能会导致死锁)。如果你让它完全同步,那么你的基本控制器在可扩展性方面不会非常高效,但它会工作得很好,直到你准备好采用适当的异步方法,例如,当迁移到 .NET Core 时。

如果基础控制器当前使用 
HttpClient

调用其 API,最后一个选项也可能是可能的:您可以使用委托处理程序来自动检索/刷新访问令牌。这实施起来有点复杂,但一旦到位就可以很好地发挥作用。如果基本控制器

不是

使用
HttpClient来调用API,则此选项不可行。

© www.soinside.com 2019 - 2024. All rights reserved.