簡體   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