C# 我所有使用IO的操作都应该是异步的吗?

C# 我所有使用IO的操作都应该是异步的吗?,c#,io,task-parallel-library,async-await,asp.net-mvc-5,C#,Io,Task Parallel Library,Async Await,Asp.net Mvc 5,在阅读MSDN文章时,我得出结论,对于I/O绑定操作,我应该始终使用async Wait 考虑以下代码,其中movieManager公开了类ORM实体框架的异步方法 public class MovieController : Controller { // fields and constructors public async Task<ActionResult> Index() { var movies = await movieMan

在阅读MSDN文章时,我得出结论,对于I/O绑定操作,我应该始终使用async Wait

考虑以下代码,其中movieManager公开了类ORM实体框架的异步方法

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);
    }
}
公共类电影控制器:控制器
{
//字段和构造函数
公共异步任务索引()
{
var movies=await movieManager.listAsync();
返回视图(电影);
}
公共异步任务详细信息(int-id)
{
var movie=await movieManager.FindAsync(id);
返回视图(电影);
}
}
  • 这是否总能给我带来更好的可扩展性和/或性能?
    • 我如何测量这个
  • 为什么在“现实世界”中不使用这个
  • 上下文同步怎么样?
    • 我不应该在ASP.NET MVC中使用异步I/O,这有那么糟糕吗
  • 我知道这些问题很多,但是关于这个话题的文献有相互矛盾的结论。有人说,对于依赖于I/O的任务,您应该始终使用async,其他人说,您根本不应该在ASP.NET应用程序中使用async

    这是否总能给我带来更好的可扩展性和/或性能

    可能吧。如果您只有一个数据库服务器作为后端,那么您的数据库可能是您的可伸缩性瓶颈,在这种情况下,扩展web服务器不会对整个服务的更广泛范围产生任何影响

    我如何测量这个

    与负载测试。如果你想要一个简单的概念证明,你可以去看看

    为什么这在“现实世界”中不经常使用

    是的。NET 4.5之前的异步请求处理程序编写起来相当痛苦,许多公司只是在这个问题上投入了更多的硬件。现在.NET4.5和
    async
    /
    await
    正在获得巨大的发展势头,异步请求处理将继续变得更加普遍

    上下文同步怎么样

    它由ASP.NET为您处理。我在我的博客上有一篇文章,解释了
    await
    如何在
    await
    任务时捕获当前的
    SynchronizationContext
    。在本例中,它是一个表示请求的
    AspNetSynchronizationContext
    ,因此像
    HttpContext.Current
    、culture等都会在
    等待点之间自动保留

    我不应该在ASP.NET MVC中使用异步I/O,这有那么糟糕吗

    一般来说,如果您使用的是.NET 4.5,您应该使用
    async
    来处理任何需要I/O的请求。如果请求很简单(即,不访问数据库或调用其他服务),则只需保持同步即可

    这是否总能给我带来更好的可扩展性和/或性能

    你自己回答的,你需要测量并找出答案。通常,由于增加了复杂性,异步是稍后要添加的内容,这是代码库中的首要问题,直到出现特定的问题为止

    我如何测量这个

    双向构建,看看哪个更快(最好是针对大量操作)

    为什么这在“现实世界”中不经常使用

    因为复杂性是软件开发中最大的问题。如果代码很复杂,则更容易出错,也更难调试。更重要的是,更难修复的bug并不是潜在性能优势的良好折衷

    上下文同步怎么样

    我假设您指的是ASP.NET上下文,如果您不应该进行任何同步,请确保只有一个线程正在访问您的上下文并通过它进行通信

    我不应该在ASP.NET MVC中使用异步I/O,这有那么糟糕吗


    引入异步只是为了处理同步,这是一种损失,除非您真的需要性能。

    在网站中使用异步代码有很多负面影响:

    • 当数据片段之间存在依赖关系时,您会遇到麻烦,因为您无法使其异步
    • 异步工作通常用于API请求之类的事情。你有没有想过你不应该在网页上这样做?如果外部服务宕机,那么您的站点也会宕机。这不符合比例
    • 在某些情况下,异步操作可能会加快站点的运行速度,但这基本上会带来麻烦。你总是等待最慢的一个,因为有时资源会因为任何原因而减速,这意味着网站减速的风险会增加一倍,相当于你正在使用的异步作业的数量。您必须引入超时来处理这些问题,然后引入错误处理代码,等等
    • 当由于CPU负载太重而扩展到多个Web服务器时,异步工作会对您造成伤害。您过去在异步代码中输入的所有内容现在都会在用户单击链接时同时启动,然后就可以轻松地关闭。这不仅适用于CPU负载,还适用于数据库负载甚至API请求。您将在所有系统资源中看到一个非常糟糕的利用率模式:大量使用的峰值,然后再次下降。这不能很好地扩展。同步代码没有这个问题:作业只有在另一个作业完成后才开始
    网站异步工作是一个陷阱:不要去那里

    将繁重的代码放在一个worker(或cron作业)中,在用户要求之前完成这些工作。您将把它们放在数据库中,并且您可以继续向站点添加功能,而不必担心触发太多异步作业等等

    网站的性能被严重高估了。当然,如果你的页面在50毫秒内呈现是很好的,但是如果需要250毫秒,人们真的不会注意到(为了测试这一点:在你的代码中放置一个
    Sleep(200)

    如果您只需将工作转移到另一个进程,并使网站成为仅连接数据库的接口,那么您的代码将变得更具可伸缩性。不要