带刺的蜗牛 发表于 2023-8-11 15:09:45

C# Task 使用 WhenAll 请求远程分页接口

首先WhenAll 是什么?

-所有提供的任务已完成时,创建将完成的任务-
-Creates a task that will complete when all of the supplied tasks have completed-
Task.WhenAll() 方法是 C# 中用于等待多个任务(Task)完成的一种方式。它不会控制并发数量,而是等待所有传递给它的任务都完成后才会继续执行下一步操作。这意味着一旦所有任务都完成,无论这些任务是如何并发执行的,Task.WhenAll() 方法才会返回。
具体用法还是去看官方文档,这是最好的教程: .NET Core 官方教程-Task.WhenAll()
请求远程分页接口并返回实体数据

我这里写的通用模板,用的Task.WhenAll 的重载方法: WhenAll(IEnumerable tasks)。
我这里为了控制并发数量,使用 SemaphoreSlim 来控制同时执行的任务数量。
SemaphoreSlim 用于控制并发数量,确保同时只有最大数量的任务在执行。每个任务在开始执行时获取信号量,完成后释放信号量,这样可以确保同时执行的任务数量不会超过预定的最大并发数。
请注意,这只是一种控制并发数量的方式之一。
以下就是我的示例:
public async Task<Result<IEnumerable<T>>> RequestRemoteDatas<T>(string token, TableDataQueryParams param, int maxConcurrentTasks = -1)
{
    try
    {
      var content = new StringContent(JsonConvert.SerializeObject(param),
                                        Encoding.UTF8, Application.Json);
      var client = _httpClientFactory.CreateClient();
      client.DefaultRequestHeaders.Add("X-Access-Token", token);
      //client.Timeout = TimeSpan.FromSeconds(30);
      string url = AppSettings.TableDataHost + AppSettings.TableDataQueryUri;

      // 发送post请求
      HttpResponseMessage response = await client.PostAsync(url, content);
      var responseContent = await response.Content.ReadAsStringAsync();
      var result = JsonConvert.DeserializeObject<QueryApiResult>(responseContent);
      if (!result.success || result.code != 200)
      {
            return Result.BadRequest<IEnumerable<T>>(result.message);
      }
      var records = JsonConvert.DeserializeObject<PlatformManagerDto<T>>(result.result.ToString());
      if (records == null)
      {
            return Result.NotFound<IEnumerable<T>>();
      }
      var dtos = new List<T>();

      if (records.Records.Any())
      {
            dtos.AddRange(records.Records);
      }

      if(records.Pages > 1)
      {
            var tasks = new List<Task<Result<IEnumerable<T>>>>();

            SemaphoreSlim? semaphore = null;
            if (maxConcurrentTasks >= 0)
            {
                //Maximum number of concurrent writes
                semaphore = new SemaphoreSlim(maxConcurrentTasks);
            }

            for (int i = 2; i <= records.Pages; i++)
            {
                int index = i;
                tasks.Add(Task.Run(async () =>
                                 {
                                       param.pageNo = index;
                                       var content1 = new StringContent(JsonConvert.SerializeObject(param),
                                                                        Encoding.UTF8, Application.Json);

                                       if (semaphore != null)
                                       {
                                           semaphore.Wait();
                                       }

                                       try
                                       {
                                           // Perform task operations
                                           // 发送post请求
                                           HttpResponseMessage response1 = await client.PostAsync(url, content1);
                                           var responseContent1 = await response1.Content.ReadAsStringAsync();
                                           var result1 = JsonConvert.DeserializeObject<QueryApiResult>(responseContent1);
                                           if (!result1.success || result1.code != 200)
                                           {
                                             return Result.BadRequest<IEnumerable<T>>(result1.message);
                                           }
                                           var records_next = JsonConvert.DeserializeObject<PlatformManagerDto<T>>(result1.result.ToString());
                                           if (records_next == null)
                                           {
                                             return Result.NotFound<IEnumerable<T>>();
                                           }
                                           return Result.Success(records_next.Records);
                                       }
                                       catch (Exception ex)
                                       {
                                           return Result.BadRequest<IEnumerable<T>>(ex.Message);
                                       }
                                       finally
                                       {
                                           if (semaphore != null)
                                           {
                                             semaphore.Release();
                                           }
                                       }                              
                                 }
                                  ));
            }

            var continuation = Task.WhenAll(tasks);
            continuation.Wait();
            if (continuation.Status == TaskStatus.RanToCompletion)
            {
                foreach (var result1 in continuation.Result)
                {
                  if (result1.Code != 200)
                  {
                        return Result.BadRequest<IEnumerable<T>>(result1.Msg);
                  }
                  dtos.AddRange(result1.Data);
                }
            }
      }
      return Result.Success(dtos.AsEnumerable());
    }
    catch (Exception ex)
    {
      return Result.BadRequest<IEnumerable<T>>(ex.Message);
    }
}总之,这篇博客希望能够为您提供有价值的信息,并激发您的思考。
或者,您有更好的建议欢迎在评论区留言。
-感谢您花时间阅读这篇博客-

来源:https://www.cnblogs.com/junsun-blogs-home/archive/2023/08/11/17622979.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: C# Task 使用 WhenAll 请求远程分页接口