当我阅读MSDN文章 Using Asynchronous Methods in ASP.NET MVC 4 时,我得出的结论是,我应该始终使用异步等待来进行I / O绑定操作。
考虑以下代码,其中movieManager公开ORM的异步方法,如Entity Framework。
public class MovieController : Controller
{
// fields and constructors
public async Task<ActionResult> Index()
{
var movies = await movieManager.listAsync();
return View(movies);
}
public async Task<ActionResult> Details(int id)
{
var movie = await movieManager.FindAsync(id);
return View(movie);
}
}
我知道这些问题很多,但关于这个主题的文献却有相互矛盾的结论。有人说你应该总是对依赖于I / O的任务使用异步,其他人说你根本不应该在ASP.NET应用程序中使用async。
答案 0 :(得分:24)
这总能给我带来更好的可扩展性和/或性能吗?
可能。如果您只有一个数据库服务器作为后端,那么您的数据库可能是您的可扩展性瓶颈,在这种情况下,扩展您的Web服务器不会对整个服务范围产生任何影响。
我该如何衡量?
进行负载测试。如果您想要一个简单的概念验证,可以查看this gist of mine。
为什么不在现实世界中使用这个&#34;很多?
是的。 .NET 4.5之前的异步请求处理程序编写起来非常痛苦,很多公司只是在这个问题上投入了更多的硬件。现在.NET 4.5和async
/ await
正在获得很大动力,异步请求处理将继续变得更加普遍。
上下文同步怎么样?
ASP.NET为您处理了这个问题。我的博客上有async
intro,其中说明await
在您SynchronizationContext
任务时如何捕获当前await
。在这种情况下,AspNetSynchronizationContext
表示请求,因此HttpContext.Current
,文化等所有内容都会自动保存在await
个点。
是不是很糟糕,我不应该在ASP.NET MVC中使用异步I / O?
作为一般规则,如果您使用的是.NET 4.5,则应使用async
来处理任何需要I / O的请求。如果请求很简单(即没有访问数据库或调用其他服务),那么只需保持同步即可。
答案 1 :(得分:2)
这总能给我带来更好的可扩展性和/或性能吗?
你自己回答,你需要测量并找出答案。通常,async是稍后要添加的,因为增加了复杂性,这是代码库中的第一个问题,直到您遇到特定问题。
我该如何衡量?
以两种方式构建它,看哪个更快(最好是大量操作)
为什么不在现实世界中使用这个&#34;很多?
因为复杂性是软件开发中的最大问题。如果代码很复杂,则更容易出错并且更难调试。更多,更难以修复错误不是一个很好的权衡性能优势。
上下文同步怎么样?
我假设您的意思是ASP.NET上下文,如果是这样,您不应该进行任何同步,请确保只有一个线程可以访问您的上下文并通过它进行通信。
是不是很糟糕,我不应该在ASP.NET MVC中使用异步I / O?
除非你真的需要性能,否则引入异步只是为了处理同步是一种损失。
答案 2 :(得分:-1)
将异步代码放在网站上有很多不利的方面:
网站的异步工作是一个陷阱:不要去那里!
将重型代码放在工作人员(或cron作业)中,在用户提出要求之前执行这些操作。您可以将它们放在数据库中,并且可以继续为站点添加功能,而不必担心会触发太多异步作业,而不必担心。
网站的效果严重受到高估。当然,如果您的页面在50ms内呈现,那就太好了,但是如果它需要250ms,那么人们真的不会注意到(测试一下:在代码中添加Sleep(200)
)。
如果您只是将工作卸载到另一个进程并使网站只是您的数据库的接口,那么您的代码将变得更具可伸缩性。不要让你的网络服务器做繁重的工作,它不应该做,它不会扩展。你可以让一百台机器每个网页共花费1个CPU小时 - 但至少它会以200ms内仍然加载的方式进行扩展。祝你用异步代码实现这一目标。
我想在此添加旁注。虽然我对异步代码的看法似乎很强,但它主要是对程序员的看法。异步代码很棒,可以产生性能差异,证明我概述的所有要点都是错误的。但是,它需要在代码中进行大量微调以避免我在本文中提到的观点,并且大多数程序员都无法处理。