c# - 运行并行任务并返回第一个完成的任务并在后台运行其他任务以保存结果
问题描述
我在 .NET CORE 3.1 中有一个 WebApi,我正在尝试从服务(其他第三方)获取结果。我在我的 API 中为同一个服务创建了多个请求,但是每个请求的某些参数是不同的,每个请求从服务返回的结果都会不同,但结果的结构将是相同的。
由于所有请求都是相互独立的,因此我想并行运行所有请求。我想从我的 API 接收到服务后立即返回第一个结果,但我也想在后台运行所有其他请求并将结果保存在 REDIS 中。
我试图创建一个示例代码来检查是否可能:
[HttpPost]
[Route("Test")]
public async Task<SearchResponse> Test(SearchRequest req)
{
List<Task<SearchResponse>> TaskList = new List<Task<SearchResponse>>();
for (int i = 0; i < 10; i++)
{
SearchRequest copyReq = Util.Copy(req); // my util function to copy the request
copyReq.ChangedParameter = i; // This is an example, many param can changed
TaskList.Add(Task.Run(() => DoSomething(copyReq)));
}
var finishedTask = await Task.WhenAny(TaskList);
return await finishedTask;
}
private async Task<SearchResponse> DoSomething(SearchRequest req)
{
// Here calling the third party service
SearchResponse resp = await service.GetResultAsync(req);
// Saving the result in REDIS
RedisManager.Save("KEY",resp);
return resp;
}
现在我想知道这是否是处理这个问题的正确方法。如果有更好的方法,请指导我。
编辑
用例场景
我创建了一个 Web 应用程序,它将从我的 webapi 获取结果并显示结果。WebApp 通过向我的 api 发送请求来搜索产品列表(可以是任何东西)。现在我的 api 创建不同的请求,因为source
(假设是 Site1 和 Site2)的结果可能不同。
现在第三方处理对不同来源(Site1 和 Site2)的所有请求,并将结果转换为我的结果结构。我只需要提供我想从哪个站点获取结果的参数,然后在我结束时调用该服务。
现在我想在任何来源(site1 或 site2)给我结果后立即将结果发送到我的 WebApp,并且在后台我想将其他来源的结果保存在 redis 中。这样我也可以在其他请求命中时从我的 webapp 中获取它。
解决方案
代码看起来不错;我只推荐一个调整:不要使用Task.Run
. Task.Run
导致线程切换,这里完全没有必要。
[HttpPost]
[Route("Test")]
public async Task<SearchResponse> Test(SearchRequest req)
{
var TaskList = new List<Task<SearchResponse>>();
for (int i = 0; i < 10; i++)
{
SearchRequest copyReq = Util.Copy(req); // my util function to copy the request
copyReq.ChangedParameter = i; // This is an example, many param can changed
TaskList.Add(DoSomething(copyReq));
}
return await await Task.WhenAny(TaskList);
}
private async Task<SearchResponse> DoSomething(SearchRequest req)
{
// Here calling the third party service
SearchResponse resp = await service.GetResultAsync(req);
// Saving the result in REDIS
RedisManager.Save("KEY",resp);
return resp;
}
请注意,这是使用即发即弃。在一般意义上,即发即弃是危险的,因为这意味着您不在乎代码是否失败或是否完成。在这种情况下,由于代码仅更新缓存,因此可以接受即发即弃。
推荐阅读
- c++ - 代码仅产生 for 循环的第一个值,例如。1
- java - 使用 Spring Cloud GCP Core 导入凭据时的 Google Cloud KMS 权限问题
- python - 松弛斜线命令图片处理
- pine-script - 为什么我设置数据的周期级别,当我更改图表的显示时间,买卖时间,次数变化时
- macos - AppleScript如何将文件复制到系统路径
- verilog - 我的 Verilog 代码正在编译,没有任何错误 - 它显示“为输出打开了 vcd 文件”,但之后没有输出
- python - 通过将当前进位添加到答案中,下一个“进位”会发生什么?
- java - 在 JSON/Gson 中搜索文本
- android - Kiosk 应用程序,通过推送通知卸载
- primefaces - Primefaces 10 数据导出与子表不工作