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

问题描述 投票:0回答:2

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

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);
    }      
}

如果不是的话,什么时候才更有意义?

c# asp.net-mvc asp.net-mvc-4 asynchronous c#-5.0
2个回答
12
投票

考虑一下。

您打电话给某人并要求他们为您做某事。当他们这样做时,您在线上等待,等待他们说“完成”。这是同步工作。称他们为“阻碍”的行为,直到他们完成工作,然后你就可以回到你正在做的事情,之后

另一种异步方式是您拨打电话,但您不必等待电话,而是挂断电话,并在他们工作时做其他事情。一旦他们给你回电话,说“已经完成”,你就回去做你需要他们的结果做的任何事情。

现在,如果你在等待期间无事可做,那么绝对不会有任何性能提升,反而会适得其反。让对方给您回电的开销反而会增加要做的工作总量。

通过上面对异步工作的描述,您的代码在等待数据访问层完成其工作时可以做些什么吗?

如果不是,那就不,不会有任何性能提升。

如果是,那么可能会带来性能提升。


现在,说了这么多,我阅读了我的答案下面的评论,然后我更仔细地重新阅读了您的代码,我相信您在这里并没有真正利用正确的异步代码。

最好的方法是使用某种能够正确执行异步 I/O 的系统或代码。您的代码调用

Task.Run
,这实际上与将另一个人放在电话前面等待您是一样的。

例如,考虑

SqlCommand
,这可能是与数据库进行通信的实际代码,它有两个有趣的方法:

现在,如果您在使用

Task.Run
创建的线程上调用第一个,您实际上仍然处于阻塞状态,您只是要求其他人为您执行此操作。

然而,第二个正如我上面所描述的。

所以在你的特殊情况下我会尽量避免使用

Task.Run
。现在,根据服务器的负载,这样做可能会更有利,但如果可以的话,我会转而使用底层对象的异步方法来正确执行此操作。


0
投票

在给定的代码中,不建议使用await Task.Run(),因为它可能会不必要地阻塞线程。 Task.Run 方法通常应用于将 CPU 密集型工作卸载到后台线程,但在本例中,它用于包装异步操作 (context.Applicants.First())。

为了提高性能,可以修改代码如下:

public async Task<TrnApplicant> GetMemberApplicantAsync(string webReferenceNumber) { using (var context = new OnlineDataContext()) { var applicant = await context.Applicants.FirstAsync( app => app.RefNo.Equals(webReferenceNumber, StringComparison.OrdinalIgnoreCase)); return GetApplicantsInGroup(applicant.ApplicantsGroupId); } }

在这段修改后的代码中,使用 FirstAsync 方法而不是 First 来异步执行数据库查询。这允许在等待数据库操作完成时释放调用线程,从而可以提高应用程序的响应能力和可扩展性。

在处理 I/O 密集型操作(例如网络请求、文件系统操作和数据库查询)时,使用 async/await 更有意义。通过使用异步操作,您可以释放线程来处理其他请求,从而提高资源利用率并提高应用程序响应能力。

© www.soinside.com 2019 - 2024. All rights reserved.