繁体   English   中英

在 ASP.Net CORE Web 请求上执行异步工作时将文件保存在磁盘上的最有效方法

[英]Most efficient way to save a file on disk while executing async work, on a ASP.Net CORE Web Request

根据我的 Web API 的请求,我将图像保存到磁盘并使用外部 API 处理它,这通常需要几秒钟。 这是一个高流量的 API,因此我想以最有效的方式设计它。 该图像采用 Base64“编码”,但这不相关。 我们可以将其视为平均 150KB 的任意字节数组(因此保存到磁盘的操作应该非常快)

工作流程是(显然,前两个操作不需要按任何顺序执行):

  • 将图像保存在磁盘上(异步)
  • 在外部 API(异步)上处理它
  • 如果之前的两个操作都成功,则返回 Ok

考虑到这一点,我把这个(简化的)代码放在一起:

public async Task<IActionResult> Post([FromBody] string imageBase64)
{
    // Convert Image
    byte[] imageByteArray = Convert.FromBase64String(imageBase64);

    // Start async Task to Save Image
    Task taskSaveImage = System.IO.File.WriteAllBytesAsync(@"C:\ImagesStorage\image.jpg", imageByteArray);

    // Execute some heavy async processing
    await ProcessOnExternalAPI(imageByteArray);

    // Guarantee that Save Image Task has completed
    await taskSaveImage;

    // Return 200 Ok
    return Ok();
}

在我看来,这段代码是将图像保存在磁盘上的最有效方法,并且还使用外部 API 处理它,同时不阻塞 ASP.Net CORE 工作线程 这是正确的,还是有一些更有效的方法来做到这一点?

此外,在两个任务(因此可能是两个线程)之间共享byte[] imageByteArray object 有什么问题吗? 我相信.Net CORE 会处理它,但我不会很高兴在生产中发现我错了。

  • Obs 1:我知道接收字节数组的 stream 可能比接收 Base64 编码的字节数组具有更好的性能。 我对此无能为力。 API 必须如此。
  • Obs 2:使用System.Net.HttpClient class 中的async方法PostAsync向外部 RESTful API(在上面的ProcessOnExternalAPI方法中)发出请求。
  • Obs 3:我最关心的是总是有工作线程来响应请求。 这不是我的 API 响应的唯一服务。
  • Obs 4:我还查看了关于 SO: Using async/await for multiple tasks但是在那边,没有关于 asp.net 核心工作线程的问题,这是我主要关心的问题。
  • Obs 5:代码是基于我对 ASP.Net CORE 异步编程的浅薄知识编写的,并且还依赖于 Microsoft 的文档: https://docs.microsoft.com/en-us/dotnet/csharp/programming- guide/concepts/async/也就是说,在这种情况下,我很想听听在异步方面有更多经验的人的意见。

这是正确的,还是有一些更有效的方法来做到这一点?

就线程而言,这是正确的:您的代码正在执行两个并发异步操作。

我确实更喜欢使用Task.WhenAll ,因为这使代码的意图更加明确(并且还处理了写入磁盘任务可能成为即发即忘的边缘情况,正如 Theodor 在评论中指出的那样):

public async Task<IActionResult> Post([FromBody] string imageBase64)
{
  // Convert Image
  byte[] imageByteArray = Convert.FromBase64String(imageBase64);

  // Start async Task to Save Image
  Task saveImageTask = System.IO.File.WriteAllBytesAsync(@"C:\ImagesStorage\image.jpg", imageByteArray);

  // Start task to call API
  Task processTask = ProcessOnExternalAPI(imageByteArray);

  // Asynchronously wait for both tasks to complete.
  await Task.WhenAll(saveImageTask, processTask);

  // Return 200 Ok
  return Ok();
}

此外,在两个任务(因此可能是两个线程)之间共享 byte[] imageByteArray object 有什么问题吗? 我相信.Net CORE 会处理它,但我不会很高兴在生产中发现我错了。

不,那里没有问题。 分享不变的价值观是安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM