在 MVC 5 操作过滤器中进行异步调用
Posted
技术标签:
【中文标题】在 MVC 5 操作过滤器中进行异步调用【英文标题】:Making an async call in an MVC 5 action filter 【发布时间】:2015-03-17 10:31:06 【问题描述】:问题
我有一个 api GET 方法来检索站点配置。我正在使用httpClient
和GetAsync()
方法来执行此操作。
HttpResponseMessage response = await client.GetAsync("api/0/config", id);
由于我需要整个站点的此配置,因此我计划为此使用全局操作过滤器。
问题
如何在 MVC 操作过滤器中调用异步方法?或者有没有更好的办法解决这个问题?
我已经查看了多个关于此的 SO 问题 (Async action filter in MVC 4),但我没有找到令人满意的解决方案。
【问题讨论】:
可以切换到 WebAPI 吗? :) @YuvalItzchakov 我希望! :) ***.com/questions/12482338/… 谢谢@VsevolodGoloviznin 我已经阅读了这篇文章,虽然它提供了解释并没有提供合适的解决方案。 好吧,因为它说没有办法以异步方式进行,所以你应该使用非异步方法 【参考方案1】:没有办法(可靠地)从 ASP.NET MVC 5 操作过滤器调用异步方法。这已经在 ASP.NET vNext 中得到修复,但是 AFAIK 没有计划在 MVC 5 中支持它。
如果您绝对必须在操作过滤器中执行此操作,则必须使用同步调用(例如,WebClient
而不是 HttpClient
)。
【讨论】:
谢谢。您是否建议不要在操作过滤器中执行类似Task.Run(() => GetSomethingAsync(id)).Result;
的操作。如果可以,您能解释一下原因吗?
@ColinBacon:您可以使用a few hacks 来尝试强制“异步同步”,但每个都有缺点。 Task.Run
将干扰 ASP.NET 线程池启发式,对可伸缩性产生负面影响。此外,Task.Run
将显式运行 GetSomethingAsync
在当前 ASP.NET 请求上下文之外 - 这是否有效取决于 GetSomethingAsync
究竟试图做什么。所以简而言之,它可能有效(对性能的影响很小),也可能无效 - 取决于您的方法的实现。
我可以确认对可扩展性的负面影响。我们有一个相当大的站点在 Azure 上运行,我正在做这件事:Task.Run(() => DoSomethingAsync).Wait()
在一个操作过滤器中。在重负载下,这会导致糟糕的性能。当线程耗尽时,请求被添加到请求队列中。 CPU 很低,因此不会添加任何实例,因为异步工作正在调用 3rd 方服务。我们最终得到了 +100 秒的响应时间。不要这样做:-)以上是关于在 MVC 5 操作过滤器中进行异步调用的主要内容,如果未能解决你的问题,请参考以下文章