我继承了一个 .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 - 请求超时。 网络服务器未能在指定时间内响应。
这会导致初始加载时间非常长 - 有时会抛出 500 - 请求超时。网络服务器未能在指定时间内响应。
这可能是由于 ASP.NET pre-Core 应用程序中的“异步代码阻塞”造成的。链接是我的博客,我在其中详细解释了僵局。
因为基本控制器返回 void,我在等待调用以确保我获得有效的访问令牌时遇到了一些问题,并且收到了它可能使用了an asynchronous module or handler completed while an asynchronous operation was still pending.
错误。
这是一个“安全网”异常,意味着代码不正确。在这种情况下,
,这是一个禁忌。 在这种情况下,任何人都可以向我提供关于如何解决此问题的建议,或者可能是一个合理的重构,以仍然实现我的目标,即不仅在我的控制器中而且在基本控制器中拥有有效的访问令牌。
。您的基本控制器中可能有一个新方法来获取访问令牌;将该方法设为你最好的选择是
一路异步
async Task
而不是 async void
,并确保在调用 API 之前对
Task
进行
await
处理。
另一种选择是使所有代码同步。理想情况下,您应该拥有(或编写)一个完全同步工作的
AccessTokenProvider.AcquireAccessToken
方法(即,不会阻塞异步代码,这可能会导致死锁)。如果你让它完全同步,那么你的基本控制器在可扩展性方面不会非常高效,但它会工作得很好,直到你准备好采用适当的异步方法,例如,当迁移到 .NET Core 时。
如果基础控制器当前使用
HttpClient
调用其 API,最后一个选项也可能是可能的:您可以使用委托处理程序来自动检索/刷新访问令牌。这实施起来有点复杂,但一旦到位就可以很好地发挥作用。如果基本控制器不是
使用
HttpClient
来调用API,则此选项不可行。