You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:18:00