所有Entity Framework方法都应该使用异步吗?

16

在 Asp.Net MVC 或 Asp.Net Web API 中,每个查询数据库的控制器动作(即使是最简单的查询)使用 async/await 模式,这是否是一个好的实践呢?

我知道使用 async/await 会增加复杂性,但即使针对最简单的查询,添加它是否值得呢?


2
理论上:是的。因为每个数据库调用都是IO绑定的,所以会阻塞线程。但实际上,只有当您的Web服务或Web应用程序具有足够高的流量时,增加的复杂性才值得这样做。 - Dai
这与流量大小无关,而是线程成为一种稀缺资源,通常它们是充足的。使用异步数据库访问几乎从不增加吞吐量。 - usr
1个回答

28

Entity Framework使用数据库并需要访问数据库服务器。使用EF,您需要连接数据库服务器并等待服务器响应您的请求。

如果您的应用程序使用磁盘或网络(例如访问数据库)的读/写操作,则它正在执行I/O操作。每个I/O操作都应该使用async / await模式,这是一个好的实践,EF6提供了许多异步操作供您使用。

I/O bound指的是计算完成所需时间主要由等待输入/输出操作完成的时间确定的情况。 来源:维基百科

一些概念:

每个ASP.Net Web API请求使用.NET Framework线程池提供的线程。如果对ASP.Net Web API操作使用同步方法,则I/O绑定操作(数据库访问)将阻塞线程并等待数据库响应。用于您的请求的线程将被阻止,并未返回线程池。

线程池使用的最大线程数为5000(.Net 4.5)。如果您的应用程序是一个大型应用程序,那么最大线程数可能会迅速达到上限。如果线程池中没有可用线程,则新请求将添加到队列中。如果您的服务器队列变满了,则会以HTTP 503状态拒绝请求,表示"服务器过于繁忙"

如果您的ASP.Net Web API操作使用async / await模式,则每个I/O绑定操作都将释放当前请求的线程。此线程可以被另一个请求使用。如果I/O限制操作完成了其任务,则另一个线程被赋予继续处理您的ASP.Net Web API动作方法的其余部分。

因此,为了回答您的问题,如果您的应用程序可能具有大量并发,请使用async/await模式来访问数据库的每个ASP.Net Web API操作。即使您的应用程序不是大型应用程序,建议始终对I/O受限操作使用async/await。

你可以查看这篇文章。它讨论了ASP.Net MVC中的“使用异步方法”,但大部分建议也适用于ASP.Net Web API。

1
是的,你说得对。但我是否应该只考虑在需要较长时间的复杂查询中使用异步?使用异步会增加任何复杂性吗? - Kahbazi
@Arvin I/O绑定操作并不意味着长时间运行的操作,而只是读/写访问可能会阻塞您的线程而不消耗大量CPU。我更新了我的答案以获得更多精确信息。 - CodeNotFound
谢谢,您知道我可以学习更多关于我的问题的任何文章或参考资料吗? - Kahbazi
@Arvin 在我的答案中添加了一个链接 :) - CodeNotFound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接