【发布时间】:2020-12-12 22:42:07
【问题描述】:
根据我的 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 对象有什么问题吗?我相信 .Net CORE 会处理它,但我不会很高兴在生产中发现我错了。
- Obs 1:我知道接收字节数组的流可能比接收 Base64 编码的字节数组具有更好的性能。我对此无能为力。这就是 API 必须的样子。
- Obs 2:使用来自
System.Net.HttpClient类的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/ 也就是说,我很想听听在这种情况下对异步有更多经验的人的意见。
【问题讨论】:
-
您对“最有效方式”的标准是什么?你用这个 API 方法完成的秒数来衡量它吗?或您使用的资源数量?还是其他方式?
-
大约在这个时候,您将开始进行基准测试。
-
@deezg 最有效的方式是它并行执行任务的方式,同时保持实际处理 asp.net 核心请求的线程畅通无阻,并可在执行前面提到的任务时处理另一个请求
-
@TheGeneral 那么目前没有明显更好的实现吗?我的担心可能是没有看到这种方法明显有问题,或者我做了一些假设,这实际上对这个实现是不正确的
-
您在这里只有 2 个简单的调用,您已经在做正确的事情(假设您不想像已经讨论过的那样采取更激烈的行动)。您也可以使用 await
Task.WhenAll,尽管执行时间不会有明显差异
标签: c# asp.net asp.net-core asynchronous async-await