【发布时间】:2013-05-16 14:58:02
【问题描述】:
我在高流量场景中有一个多层 C# MVC4 Web 应用程序,它为各种存储库使用依赖注入。这非常有用,因为它易于测试,并且在生产中我们可以轻松地为特定控制器配置存储库。所有控制器都继承自 AsyncController,因此返回 Task<JsonResult> 或 Task<ActionResult> 的操作方法真正帮助我们的服务器扩展更多用户和 solve for the dreaded thread starvation problem。一些存储库使用 Web 服务,我们绝对可以使用 Async/Await 来提供可扩展性优势。在其他情况下,有些人可能使用无法安全线程化的非托管服务,其中 async/await 不会提供任何好处。每个存储库都是一个接口 IRepository 的实现。简而言之,每种实现在获取数据的方式上都大不相同。此配置是在部署时通过 web.config 更改和 Autofac 模块选择的。
在这样的应用程序中实现 async/await 的推荐方法有哪些?为了使该模式适合我现有的应用程序,我必须更改接口以返回Task<MyBusinessObject>。 但这不是更多的实现细节吗?我可以提供两个方法存根,GetData 和 GetDataAsync,但对我来说,这不允许我现在使用 IoC 框架,如Autofac,我可以轻松地交换所有内容,而无需更改代码。
Async/Await 的一位 Microsoft 开发人员发表了一篇博文“Should I expose an asynchronous wrapper for my synchronous methods?”,这就是问题所在。如果您的异步方法不是真正的异步(提供本机 I/O 优势),那么它实际上只会增加开销。换句话说,它不会提供任何可扩展性优势。
我只是想知道社区的其他成员是如何解决这个问题的。
【问题讨论】:
-
async和await只是将阻塞方法转换为非阻塞方法的抽象。您可以在代码中的任何位置执行此操作,而无需更改接口,除非您想强制接口方法始终是异步的。 -
如果在整个调用堆栈中都没有 Task
,那么它永远不会被异步调用。因此,您必须将其放在界面中以始终返回 Task . -
我不是这么说的。我说的是您可以使用
async和await将任何方法转换为异步方法,包括您在接口上已有的任何阻塞方法。原始方法不需要Task<TResult>返回类型。当然,将所有接口方法替换为async等效项是完全有效的,但这不是必需的。 -
这没有任何好处,它实际上增加了开销。查看 Stephen Toub 的博客文章,“我应该为我的同步方法公开一个异步包装器吗?” blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx
-
@CyanLite:当您不在整个调用堆栈中使用 Task
时,您的代码可以异步工作,但在这种情况下,您将无法从 IO 完成端口线程中受益,这在您的情况下似乎至关重要.
标签: c# interface repository-pattern async-await