使用RestSharp发起分页并行请求仅部分数据到达问题求助
问题排查与修复方案
核心错误点
- 未等待异步请求完成:调用
client.ExecuteAsync(request)时没有加await,外层Task.Run包裹的任务会在触发请求后直接判定为完成,Task.WaitAll只会等待请求触发动作完成,不会等请求本身发送、响应完成,方法退出后大量未完成的请求会被直接回收,导致数据丢失。 - 请求体格式错误:你已经手动将分页数据序列化为JSON字符串,再调用
AddJsonBody()时,RestSharp会对传入的字符串做二次序列化,最终请求体变成带转义符的字符串格式,服务端无法正常解析,直接拒绝处理。 - 空检查顺序错误:
if (listOfResults.Count() == 0 || listOfResults == null)先访问Count()再判断是否为null,当listOfResults为null时会直接抛出空引用异常。 - 并发连接数限制:
ServicePointManager.DefaultConnectionLimit默认值为2,同一时间对同一域名最多只能发起2个请求,大量并发请求会排队超时,且SecurityProtocol的设置不需要每次调用方法都重复配置,建议放在程序启动时全局设置。 - 无错误处理逻辑:没有判断请求响应的状态,即使服务端返回4xx/5xx错误你也无法感知,会误判为数据发送成功。
- 入参未使用:方法传入的
days参数没有用到,查询数据时硬编码了-31,属于逻辑瑕疵。
修复后的代码
// 建议将RestClient改为单例复用,避免重复初始化消耗资源,且RestSharp 107+版本RestClient是线程安全的 private static readonly RestClient _client = new RestClient() { Proxy = new WebProxy("xxx.xxx.xxx.xxx") { UseDefaultCredentials = true } }; // 程序启动时全局配置一次即可 // System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // 调高并发连接数,可根据服务端承受能力调整为10-100不等 // System.Net.ServicePointManager.DefaultConnectionLimit = 20; public void SendResultsByFireForget(string env, string transactionId, int days) { if (string.IsNullOrEmpty(transactionId)) { throw new ArgumentException("Parameter transactionId is null or empty!"); } if (string.IsNullOrEmpty(env)) { throw new ArgumentException("Parameter uri is null or empty!"); } List<Result> listOfResults = Repository.GetResultsByIntervalPerDay(-days); // 修正为使用传入的days参数 // 先判断null,再判断长度 if (listOfResults == null || listOfResults.Count == 0) { throw new Exception("The list of results is empty or null"); } var tasks = new List<Task>(); foreach (List<Result> page in GetPages(listOfResults, 500)) { var currentPageCopy = page; var task = Task.Run(async () => { var request = new RestRequest( $"{env.Trim()}/results1/?transaction_id={transactionId.Trim()}", Method.POST); // 直接传分页对象,让AddJsonBody自动序列化,避免二次序列化问题 request.AddJsonBody(currentPageCopy); // 等待请求完成 var response = await _client.ExecuteAsync(request); if (!response.IsSuccessful) { // 此处可添加失败日志、重试逻辑,记录失败的分页数据后续补推 Console.WriteLine($"请求失败,状态码:{response.StatusCode},错误信息:{response.ErrorMessage}"); } }); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); }
额外优化建议
- 可以添加重试逻辑,针对网络波动、服务端限流等场景自动重试失败的请求,避免数据丢失。
- 建议对分页数据做幂等性处理,避免重试时产生重复数据。
- 可以添加进度监控,实时统计成功/失败的分页数量,方便排查问题。
内容的提问来源于stack exchange,提问作者Renan
相关产品推荐
相关产品推荐

