【问题标题】:Using async & await .net 4.5 mvc c#使用 async & await .net 4.5 mvc c#
【发布时间】:2015-04-04 04:55:26
【问题描述】:

我一直在试验一些需要在地方重构的旧代码,并通过异步上传文件(服务器端)测试是否对 iis 线程等有任何改进。使用jQuery文件上传客户端。

原代码

[HttpPost]
public ActionResult UploadDocument( HttpPostedFileBase uploadedFile ) {

  // Do any validation here

  // Read bytes from http input stream into fileData
  Byte[] fileData;

  using ( BinaryReader binaryReader = 
          new BinaryReader( uploadedFile.InputStream ) ) {

    fileData = binaryReader.ReadBytes( uploadedFile.ContentLength );

  }

  // Create a new Postgres bytea File Blob ** NOT Async **
  _fileService.CreateFile( fileData );

  return Json(
    new {
      ReturnStatus = "SUCCESS" // Or whatever
    }
  );

}

新代码

[HttpPost]
public async Task<ActionResult> UploadDocumentAsync( HttpPostedFileBase uploadedFile ) {

  // Do any validation here

  // Read bytes from http input stream into fileData
  Byte[] fileData = new Byte[uploadedFile.ContentLength];

  await uploadedFile.InputStream.ReadAsync( fileData, 0, uploadedFile.ContentLength );

  // Create a new Postgres bytea File Blob ** NOT Async **
  _fileService.CreateFile( fileData );

  return Json(
    new {
      ReturnStatus = "SUCCESS" // Or whatever
    }
  );

}

新方法似乎可以正常工作,但我的问题是:

下面的代码是正确的(最好的)方法吗?这样做有什么问题吗?那里有很多相互矛盾和过时的信息。关于实际这样做是否有任何改进或意义,似乎也有很多争论。是的,它将线程返回给 iis 等,但值得进行开销类型的辩论。

有问题的代码

// Read bytes from http input stream into fileData
Byte[] fileData = new Byte[uploadedFile.ContentLength];

await uploadedFile.InputStream.ReadAsync( fileData, 0, uploadedFile.ContentLength );

【问题讨论】:

  • async /await 是我认为的摇尾巴。希望看到一些证明我错了的论点。这是一个很好的问题。因此,它几乎肯定会被某些交叉守卫管理员删除。
  • 你为什么不让 CreateFile 也异步?这是一个测试问题,看看你是否有一个特定的常见误解。同时,我想向您推荐我对这个主题的处理:stackoverflow.com/a/25087273/122718stackoverflow.com/a/12796711/122718
  • usr 我可能会,但这并不是我真正要问的。尽管在该主题上,关于快速本地数据库访问是否更快保持同步存在很多争论。

标签: c# multithreading asynchronous async-await .net-4.5


【解决方案1】:

代码是正确的。使用异步 IO 不是全部或全部。您可以安全地混合同步和异步 IO,就像您所做的那样。

Whether you should be using async has been covered already. 对于 ASP.NET,基本规则是在操作可能具有非常高的延迟并且同时被大量调用的情况下使用它。只有在这种情况下才重要的是不要释放线程。如果操作很快或很少,那么没有多少线程可以释放,这是在浪费开发人员的时间。

从缓冲(默认)输入流中读取与从文件中读取相同。 ASP.NET 缓冲长输入到磁盘上的文件。这是异步 IO 不提供吞吐量增益的经典案例。快速文件可能会被完全缓存,因此 IO 完全基于 CPU(来自缓存的 memcpy)。完全浪费开发时间和 CPU 周期。一点好处都没有。

【讨论】:

  • 那么在这种情况下,您是否会说异步文件上传是一件好事。
  • 我的建议:由于您可能只有很少的并发上传,所以这个问题没有实际意义。使用同步的默认值。如果您真的希望这是异步的,请使上传无缓冲。这是某处的 ASP.NET 设置。
  • 这是一个被误解的主题和很多相互矛盾的信息。现在以异步方式执行它并没有帮助它变得非常“时尚”。
  • 确实如此。在我的回答中,我正在进行一场圣战,以使人们摆脱这种时尚。服务器上的异步很少有好的用途(但它们存在)。
  • 听起来您应该进行测试。编写一个上传缓慢的客户端并启动数百个。
【解决方案2】:

具体回答您的问题:

  1. 您的代码没有任何问题,我认为您应该继续进行该更改。根据各种因素(指出的文件大小/缓冲、并发性等),它可能会或可能不会做出显着的改进(任何改进都将是可伸缩性,而不是速度),但您几乎肯定不会em>更糟了。你说的“开销”涉及到编译器写的状态机,大部分情况下是nearly negligable

  2. 我能想到的一个小问题:你想看看await之后发生了什么,并确保没有假设该代码将在与await 之前的代码相同的线程。在这种情况下不太可能,但需要注意一些事情。

我不同意异步是一种“时尚”,在服务器上没有什么好的用途。这是对硬件趋势的直接反应。处理器速度并没有像以前那样增加。如今,更多内核的竞赛正在展开,我们看到编程语言和框架对这一趋势做出了反应,其特性使得编写软件以利用硬件级别的并发性变得更加容易。

相对长时间运行的 I/O 在服务器应用程序中很常见(处理文件、调用外部 API 等),并且在这些操作期间释放线程以执行其他工作几乎总是一种好处。

【讨论】:

    猜你喜欢
    • 2013-04-29
    • 2012-10-16
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    相关资源
    最近更新 更多