在 MVC 5 操作过滤器中进行异步调用

Posted

技术标签:

【中文标题】在 MVC 5 操作过滤器中进行异步调用【英文标题】:Making an async call in an MVC 5 action filter 【发布时间】:2015-03-17 10:31:06 【问题描述】:

问题

我有一个 api GET 方法来检索站点配置。我正在使用httpClientGetAsync() 方法来执行此操作。

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 操作过滤器中进行异步调用的主要内容,如果未能解决你的问题,请参考以下文章

MVC2 一次异步调用,多次异步更新

如果我不等待它,是不是保证从 Mvc.Controller 操作方法调用的异步方法完成? [复制]

动作过滤器:如何调用服务层和异步方法

在异步控制器中使用同步操作

mvc中的异步页面加载

使用 AngularJS 调用异步控制器操作方法