Web应用程序中的数据访问应该在不同的任务上运行

gui*_*e31 2 c# asp.net multithreading asynchronous asp.net-web-api

我正在编写一系列ASP.Net Web Api服务,它们基本上从数据库中获取数据并将其返回.

我们现在决定重用之前写得不好的数据访问对象(让我们称之为PoorDAO),这些对象使用ADO.Net来调用数据库中的存储过程.

未来的一个改进是重写该数据访问层以受益于使用Entity Framework的异步数据调用.

因此,我们决定PoorDAO在Repositories中实现一个实现暴露异步方法的接口.我们的想法是为将来的EF异步存储库保留相同的接口:

// future common interface
public interface ICountryRepository
{
  Task<Country> GetAllCountries();
}

// current implementation hiding a PoorDAO in shame
public class CountryRepository : ICountryRepository
{
  public Task<Country> GetAllCountries()
  {
    var countries = PoorCountryDAO.GetAllcountries(); // poor static API call

    // some data transformation ...

    return Task.FromResult(result);
  }
}
Run Code Online (Sandbox Code Playgroud)

我们这里所拥有的基本上是隐藏在异步服装中的同步操作.这一切都很好,但我的问题是:虽然我们处于这种状态,但是让方法完全异步并且调用await Task.Run(() => poorCountryDAO.GetAllcountries())而不是仅仅是更好poorCountryDAO.GetAllcountries()吗?

据我所知,这将释放当前正在运行Web Api服务HTTP请求的IIS线程,并创建或重用另一个线程.该线程将被阻塞,等待DB响应而不是被阻塞的IIS线程.这有更好的资源明智吗?我是否完全误解或过度解释了Task.Run()的工作原理?

编辑:我遇到过这篇文章,声称在某些情况下,异步数据库调用可以带来8倍的性能提升.他的情景非常接近我的.考虑到这里的答案,我无法理解如何做到这一点,对于做什么感到有点困惑......

Ste*_*ary 6

这有更好的资源明智吗?

没有; 它可能更糟糕.现有的Task.FromResult并且await是最好的解决方案.

Task.Run,Task.Factory.StartNewTask.Start不应该在ASP.NET应用程序中使用.它们从ASP.NET使用的同一个线程池中窃取线程,导致额外的线程切换.此外,如果它们长时间运行,它们将混淆默认的ASP.NET线程池启发式,可能导致它不必要地创建和销毁线程.