[英]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.根据我的 Web API 的请求,我将图像保存到磁盘并使用外部 API 处理它,这通常需要几秒钟。 This is a high traffic API, thus I would like to design it in the most efficient way.这是一个高流量的 API,因此我想以最有效的方式设计它。 The image comes in Base64 "encoding", but this is not pertinent.该图像采用 Base64“编码”,但这不相关。 We can think about it as an arbitrary byte array of 150KB in average (so the saving to disk operation should be really fast) .我们可以将其视为平均 150KB 的任意字节数组(因此保存到磁盘的操作应该非常快) 。
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 .在我看来,这段代码是将图像保存在磁盘上的最有效方法,并且还使用外部 API 处理它,同时不阻塞 ASP.Net CORE 工作线程。 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)?此外,在两个任务(因此可能是两个线程)之间共享byte[] imageByteArray
object 有什么问题吗? 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.我相信.Net CORE 会处理它,但我不会很高兴在生产中发现我错了。
ProcessOnExternalAPI
method above) is made using the async
method PostAsync
from System.Net.HttpClient
class. Obs 2:使用System.Net.HttpClient
class 中的async
方法PostAsync
向外部 RESTful API(在上面的ProcessOnExternalAPI
方法中)发出请求。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):我确实更喜欢使用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();
}
Also, there is any problem to share the byte[] imageByteArray object between the two Tasks (hence possibly two threads)?此外,在两个任务(因此可能是两个线程)之间共享 byte[] imageByteArray object 有什么问题吗? 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.我相信.Net CORE 会处理它,但我不会很高兴在生产中发现我错了。
No, no problems there.不,那里没有问题。 It's safe to share values that don't change.分享不变的价值观是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.