在数据访问层中使用异步时是否有任何性能提升?

Vis*_*and 2 c# asp.net-mvc asynchronous c#-5.0 asp.net-mvc-4

如果我在数据访问层中使用Async功能,我怀疑是否有任何性能提升,如下所示:

public async Task<IEnumerable<TrnApplicant>> GetAllMemberApplicantsAsync(String webReferenceNumber)
{
    using (var context = new OnlineDataContext())
    {
        var applicant = await Task.Run(() => context.Applicants.First(
                app => app.RefNo.Equals(webReferenceNumber, StringComparison.OrdinalIgnoreCase)) );

        return GetApplicantsInGroup(applicant.ApplicantsGroupId);
    }      
}
Run Code Online (Sandbox Code Playgroud)

如果不是什么时候更有意义呢?

ang*_*son 11

考虑一下.

你打电话给别人并要求他们为你做点什么.当他们这样做的时候,你在排队等待他们说"已经完成".这是同步工作.称他们为"块",直到他们与完成任务,然后你就可以回来,无论你在做什么,的行为之后.

替代的,异步的方式,是你打电话,但不是在电话上等你挂断,并在他们工作时做其他事情.一旦他们给你回电话,说"已经完成了",你就会回去做你需要做的任何事情.

现在,如果你在等待时无所事事,那么绝对没有性能上的提升,而恰恰相反.让对方给你回电的开销将增加到要完成的工作总量.

因此,通过上面对异步工作的描述,在等待数据访问层完成其工作时,您是否有任何代码可以执行的操作?

如果没有,那么不,没有性能提升.

如果是,则可能会有性能提升.


现在,说了这么多,我读到了我的答案下面的评论,然后我仔细阅读了你的代码,我相信你并没有真正利用正确的异步代码.

最好的方法是使用某种正确进行异步I/O的系统或代码.您的代码呼叫Task.Run,实际上只是在电话前掠夺另一个人,等待您.

例如,考虑一下SqlCommand,这可能是与数据库进行对话的实际代码,它有两个有趣的方法:

现在,如果你打电话给第一个,在创建的线程上Task.Run,你实际上仍在阻止,你只是要求其他人为你做.

然而,第二个是我上面所描述的.

因此,在您的特定情况下,我会尽量避免使用Task.Run.现在,根据服务器的负载,这样做可能是有利的,但如果可以,我将切换到使用底层对象的异步方法来正确执行它.

  • 在这种特殊情况下,还有一件事需要考虑.异步行为是通过`Task.Run`完成的,相当于抓住最近的暖体以排队等候.这是最糟糕的一种异步,因为你失去了一个温暖的身体(一个线程),这可能正在做一些其他有用的工作,并且你增加了所有这些打电话的复杂性. (3认同)
  • 此外,如果后端可以比ASP.NET服务器进一步扩展,那么正确的"异步"只有一个好处. (3认同)