使用异步和等待 .net 4.5 mvc c#

Using async & await .net 4.5 mvc c#

我一直在试验一些需要在某些地方重构的旧代码,并且正在测试通过异步上传文件(服务器端)是否对 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 );

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

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

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

具体回答您的问题:

  1. 您的代码没有任何问题,我认为您应该继续进行该更改。根据各种因素(指出的文件 sizes/buffering、并发性等),它可能会或可能不会做出明显的改进(任何改进都将在可扩展性方面,而不是速度方面),但你几乎肯定不会更糟。你说的"overhead"涉及到编译器写的状态机,大多数情况下是

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

我不同意异步是 "fad" 在服务器上几乎没有什么用处的观点。这是对硬件趋势的直接反应。处理器速度没有像以前那样增加。如今,更多核心的竞争已经开始,我们看到编程语言和框架对这一趋势作出反应,其特性使得编写软件更容易利用硬件级并发性。

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