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):
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.
ProcessOnExternalAPI
method above) is made using the async
method PostAsync
from System.Net.HttpClient
class. 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.