运行并行任务并返回第一个完成的任务,在后台运行其他任务以保存结果

uqxowvwt  于 2021-06-09  发布在  Redis
关注(0)|答案(1)|浏览(337)

我在.NETCore3.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通过向myapi发送请求来搜索产品列表(可以是任何产品)。现在,我的api创建不同的请求作为 source (假设site1和site2)的结果可能不同。
现在,第三方处理对不同源(site1和site2)的所有请求,并将这些结果转换为我的结果结构。我只需提供参数,从哪个网站,我想得到的结果,然后在我的服务调用结束。
现在我想在任何源(site1或site2)给出结果后立即将结果发送到我的webapp,并且在后台我想将其他源的结果保存在redis中。这样我就可以在其他请求命中时从我的网络应用程序中获取。

js81xvg6

js81xvg61#

代码看起来不错;我只建议做一个调整:不要使用 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;            
}

请注意,这是使用火和忘记。在一般意义上,fire-and-forget是危险的,因为它意味着您不关心代码是否失败或者是否完成。在这种情况下,因为代码只更新缓存,所以可以接受fire和forget。

相关问题