我对在ASP中使用异步操作有一些担忧。净MVC。什么时候它能提高应用程序的性能,什么时候不能?

在ASP中处处使用异步操作好吗?净MVC吗? 关于可等待方法:当我想查询数据库(通过EF/NHibernate/其他ORM)时,我应该使用async/await关键字吗? 在一个操作方法中,我可以使用await关键字异步查询数据库多少次?


当前回答

我的5美分:

当且仅当你做IO操作时使用async/await,比如DB或外部服务webservice。 总是选择异步调用而不是DB。 每次查询DB时。

附注:第一点有例外情况,但你需要很好地理解异步内部。

作为一个额外的优势,如果需要,你可以并行执行很少的IO调用:

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result

其他回答

在ASP中处处使用异步操作好吗?净MVC吗?

在任何可以使用异步方法的地方这样做都是很好的,特别是当你在工作进程级别有性能问题时,这发生在大量数据和计算操作中。否则,不需要,因为单元测试将需要强制转换。

关于可等待方法:我是否应该使用async/await关键字当我 想查询一个数据库(通过EF/NHibernate/其他ORM)?

是的,最好对任何DB操作使用异步,以尽可能避免工作进程级别的性能问题。 注意,EF已经为大多数操作创建了许多异步选项,例如:

.ToListAsync()
.FirstOrDefaultAsync()
.SaveChangesAsync()
.FindAsync()

我可以使用await关键字查询数据库多少次 异步在一个单一的动作方法?

前途无量

在ASP中处处使用异步操作好吗?净MVC吗?

在编程中,这要视情况而定。在走某条路的时候总是要权衡取舍的。

async-await shines in places where you know you'll receiving concurrent requests to your service and you want to be able to scale out well. How does async-await help with scaling out? In the fact that when you invoke a async IO call synchronously, such as a network call or hitting your database, the current thread which is responsible for the execution is blocked waiting for the request to finish. When you use async-await, you enable the framework to create a state machine for you which makes sure that after the IO call is complete, your method continues executing from where it left off.

需要注意的一点是,这个状态机有一个微妙的开销。使方法异步化并不会使它执行得更快,这是需要理解的一个重要因素,也是许多人存在的一个误解。

在使用async-await时需要考虑的另一件事是,它始终是异步的,这意味着您将从上到下看到async贯穿整个调用堆栈。这意味着如果您想公开同步API,您将经常发现自己重复了一定数量的代码,因为异步和同步不能很好地混合在一起。

我应该使用异步/等待关键字当我想查询数据库(通过 EF / NHibernate /其他ORM) ?

如果您选择使用异步IO调用,那么是的,async-await将是一个不错的选择,因为越来越多的现代数据库提供者公开了实现TAP(任务异步模式)的异步方法。

多少次我可以使用等待关键字查询数据库 异步在一个单一的行动方法?

只要您遵守数据库提供商规定的规则,您想要多少就有多少。异步调用的数量没有限制。如果您有相互独立且可以并发执行的查询,则可以为每个查询旋转一个新任务并使用await task。WhenAll等待两者都完成。

我的经验是,今天很多开发人员使用async/await作为控制器的默认设置。

我的建议是,只有在你知道它对你有帮助的时候才使用它。

原因是,正如Stephen Cleary和其他人已经提到的,它会引入性能问题,而不是解决问题,并且它只会在特定的场景中帮助您:

高流量控制器 可伸缩的后端

我的5美分:

当且仅当你做IO操作时使用async/await,比如DB或外部服务webservice。 总是选择异步调用而不是DB。 每次查询DB时。

附注:第一点有例外情况,但你需要很好地理解异步内部。

作为一个额外的优势,如果需要,你可以并行执行很少的IO调用:

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result

当一个动作必须执行几个独立的长时间运行的操作时,异步动作方法非常有用。

AsyncController类的典型用途是长时间运行的Web 服务调用。

我的数据库调用应该是异步的吗?

IIS线程池通常可以处理比数据库服务器更多的并发阻塞请求。如果数据库是瓶颈,异步调用将不会加快数据库响应。在没有节流机制的情况下,通过使用异步调用将更多的工作高效地分配到不堪重负的数据库服务器,只会将更多的负担转移到数据库。如果您的DB是瓶颈,异步调用将不是灵丹妙药。

你应该看一下第一和第二篇参考文献

源自@PanagiotisKanavos评论:

此外,异步并不意味着并行。异步执行释放 有价值的线程池线程从阻塞外部资源,为 没有复杂性或性能成本。这意味着同一台IIS机器可以 处理更多并发请求,并不是说它会运行得更快。 您还应该考虑阻塞调用以 cpu密集型spinwait。在压力大的时候,阻止电话会 导致不断升级的延迟和应用程序池回收。异步调用 避免这种情况