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,正如您所做的那样。

是否应该使用async已经介绍过了。对于ASP。NET的基本规则是在操作可能具有非常高的延迟并且同时被大量调用的情况下使用它。只有在这种情况下,不释放线程才是重要的。如果操作很快或很少,那么就没有多少线程可以释放,这是浪费开发人员的时间。

从缓冲(默认)输入流中读取与从文件中读取相同。ASP。NET缓冲磁盘上文件的长输入。这是异步IO不能提高吞吐量的典型情况。在fast中,文件可能是完全缓存的,因此IO完全基于CPU(来自缓存的memcpy)。开发时间和CPU周期的总浪费。没有任何好处。

具体回答您的问题:

  1. 您的代码没有任何问题,在我看来,您应该继续进行更改。根据各种因素(如所指出的文件大小/缓冲、并发性等),它可能会也可能不会有显著的改进(任何改进都将是在可扩展性方面,而不是速度方面),但几乎可以肯定的是,你不会变得更糟。你所说的"开销"涉及编译器编写的状态机,在大多数情况下几乎可以忽略。

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

我不同意异步是一种"时尚",在服务器上几乎没有什么好的用途。这是对硬件趋势的直接回应。处理器的速度并没有像以前那样增长。今天的竞争是争夺更多的核心,我们看到编程语言和框架对这一趋势做出了反应,其功能使编写软件更容易利用硬件级别的并发性。

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