简体   繁体   中英

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

On a request on my Web API, I'm saving a image to the disk and also processing it with an external API which usually takes several seconds. This is a high traffic API, thus I would like to design it in the most efficient way. The image comes in Base64 "encoding", but this is not pertinent. We can think about it as an arbitrary byte array of 150KB in average (so the saving to disk operation should be really fast) .

The workflow is (the first two operations don't need to execute in any order, obviously):

  • Save image on disk (async)
  • Process it on an external API (async)
  • Return Ok in case of both previous operations succeed

With that in mind, I put together this (simplified) code:

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();
}

This code seems to me the most efficient way to save the image on disk, and also process it with the external API, both at the same time while not blocking the ASP.Net CORE working thread . Is that right, or there is some more efficient way to do it?

Also, there is any problem to share the byte[] imageByteArray object between the two Tasks (hence possibly two threads)? I believe that.Net CORE would take care of it, but I would not be happy to discover that i'm wrong once in production.

  • Obs 1: I know that receiving a stream for the byte array may lead to a better performance than receiving a Base64 encoded byte array. I have no control over that. It's how the API has to be.
  • Obs 2: The request to the external RESTful API (inside the ProcessOnExternalAPI method above) is made using the async method PostAsync from System.Net.HttpClient class.
  • Obs 3: My biggest concern is always have Working Threads to respond to the requests. This is not the only service that my API respond to.
  • Obs 4: I also checked out this question/answer on SO: Using async/await for multiple tasks But over there, there is no concern about the asp.net core working threads, which is my main concern.
  • Obs 5: The code is made based on my humble knowledge of async programming on ASP.Net CORE, and also relying on the this Microsoft's Documentation: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ That said, I would love to hear from someone with more experience on async, on this type of scenario.

Is that right, or there is some more efficient way to do it?

In terms of threads, that is correct: your code is doing two concurrent asynchronous operations.

I do prefer using Task.WhenAll , since that makes the intent of the code more explicit (and also handles an edge case where the write-to-disk task can become fire-and-forget, as noted by Theodor in the comments):

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();
}

Also, there is any problem to share the byte[] imageByteArray object between the two Tasks (hence possibly two threads)? I believe that.Net CORE would take care of it, but I would not be happy to discover that i'm wrong once in production.

No, no problems there. It's safe to share values that don't change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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