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<TResult>(IEnumerable<Task<TResult>> 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);
    }
}

总之,这篇博客希望能够为您提供有价值的信息,并激发您的思考。

或者,您有更好的建议欢迎在评论区留言。

-感谢您花时间阅读这篇博客-

posted @ 2023-08-11 14:49  Meitoo_O  阅读(315)  评论(0编辑  收藏  举报