由于一些优化问题,我决定将控制器的操作方法重写为异步操作方法。它是一个多层应用程序,从那时起,我面临一个架构问题,我想知道下面将展示两个approches之间的主要区别。假设我的同步方法是:
public virtual ActionResult Method()
{
SomeLogic.LargeOperation();
return View(...);
}
LargeOpertation做了很多。这是伪代码:
public void LargeOpertion() {
DatabaseManipulations1();
IndependentWork();
CallingToWebService1();
IndependentWork();
DatabaseManipulations2();
IndependentWork();
CallingToWebService2();
IndependentWork();
}
LargeOperations中的每个方法本身都有几个方法,依此类推......问题是:我是否需要将它们全部异步并在几乎每个应用程序层中使用await?
public virtual Task<ActionResult> Method()
{
await SomeLogic.LargeOperation();
return View(...);
}
public async Task LargeOpertion() {
await DatabaseManipulations1();
IndependentWork();
await CallingToWebService1();
IndependentWork();
await DatabaseManipulations2();
IndependentWork();
await CallingToWebService2();
IndependentWork();
}
或者我可以像这样在LargeOpertaion上使用任务:
public virtual Task<ActionResult> Method()
{
await Task.Run(() => SomeLogic.LargeOperation());
return View(...);
}
我们还假设IndependentWork()不是那么大。
答案 0 :(得分:4)
由于一些优化问题,我决定将控制器的操作方法重写为异步操作方法。
在你开始之前,你应该意识到async
会为你做什么以及它不会。
异步操作运行速度不快。因此,对数据库的异步调用并不比对数据库的同步调用快。
await
不会提前返回浏览器。它只是将当前线程释放回ASP.NET线程池。
因此,每个单独的请求仍然需要相同的总时间(实际上,只是稍微更长,但不是可检测的数量)。
async
帮助的是可伸缩性 - 即应用程序使用相同资源处理更多请求的能力。但是,它只会有助于 Web应用程序的可扩展性 - 它无法神奇地进入您的数据库并使 扩展。因此,如果您的可伸缩性瓶颈是您的数据库而不是ASP.NET(通常就是这种情况),那么async
根本无法帮助您。
如果您的数据库后端是可扩展的(例如,NoSQL,Azure SQL或数据库集群),并且如果您的ASP.NET应用程序需要扩展,那么您可以从async
中受益。
我是否需要将它们全部异步并在几乎每个应用程序层中使用await?
最好的方法是从“叶子”开始 - 最低级别的方法 - 并从那里开始工作。在这种情况下,从数据库交互开始,首先将它们转换为async
。
但是,您在任何时候都不应使用Task.Run
或Task.Factory.StartNew
。相反,请使用真正的异步API,例如EF6中的async
支持。