多层C#应用程序中的异步/等待

Tim*_* P. 14 c# interface repository-pattern async-await

我在高流量场景中有一个多层C#MVC4 Web应用程序,它使用依赖注入来处理各种存储库.这非常有用,因为它易于测试,在生产中我们可以轻松配置特定控制器的存储库.所有控制器都继承自AsyncController,因此返回Task<JsonResult>Task<ActionResult>真正帮助我们的服务器的操作方法可以扩展到更多用户并解决可怕的线程饥饿问题.一些存储库使用Web服务,我们绝对可以使用Async/Await来提供可伸缩性优势.在其他情况下,有些可能会使用无法安全线程的非托管服务,其中async/await将不会带来任何好处.每个存储库都是一个接口IRepository的实现.简而言之,每种实现方式在获取数据方面都有很大差异.在部署时使用web.config更改和Autofac模块选择此配置.

在这样的应用程序中实现async/await的一些推荐方法是什么?为了使模式适合我现有的应用程序,我必须更改接口以返回Task<MyBusinessObject>. 但这不是一个实现细节吗? 我可以提供两个方法存根,GetDataGetDataAsync,但对我来说,不会允许灵活性我现在有IoC框架类似Autofac在那里我可以一切轻松更换,而无需更改代码.

Async/Await的一位微软开发人员发布了一篇博文," 我应该为我的同步方法公开一个异步包装器吗? ",这种问题就出现了.如果您的异步方法不是真正的异步(提供本机I/O好处),那么它实际上只会增加开销.换句话说,它不会提供任何可扩展性优势.

我只是想社区的其他成员如何解决这个问题.

Ste*_*ary 15

在您的情况下,我建议您的接口异步:

public interface IMyInterface
{
  Task<TMyResult> GetDataAsync();
}
Run Code Online (Sandbox Code Playgroud)

对于同步方法,您可以返回Task.FromResult:

public class MyImplementation : IMyInterface
{
  public Task<TMyResult> GetDataAsync()
  {
    TMyResult ret = ...;
    return Task.FromResult(ret);
  }
}
Run Code Online (Sandbox Code Playgroud)

当然可以async使用异步方法await.

关于实施细节,我会说"是和否".;)IDisposable在这方面非常相似.从逻辑上讲,它是一个实现细节,因为它实现的方式无关紧要.在调用代码需要以不同方式处理它的意义上,它不是实现细节.所以我同意 - 逻辑上 - 这是一个实现细节,但.NET平台还不够先进,不能对它进行处理.

或者,您可以这样想(这是我通常给出的解释):async是实际的实现细节,当您返回Task<T>T,您将定义一个实现可能是异步的接口.

我有一系列博客文章,涉及async"大型"设计(即,适应asyncOOP而不是允许其功能).我解决了一些常见问题,如异步初始化和IoC.这只是一个人的意见,但我不知道有任何其他资源可以解决这些问题.

PS你不需要继承AsyncControllerMVC4.默认控制器处理程序将async根据其返回类型(TaskTask<T>)自动检测方法.