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

为何Task会被取消?多线程API压测代码异常排查

问题原因及修复方案

核心错误点

  1. 同步阻塞异步操作引发死锁/任务取消
    CallApiAndGetStatusCode中使用httpClient.SendAsync(request).Result同步阻塞异步方法,在存在同步上下文的环境(如ASP.NET、UI程序)中,会导致异步回调无法回到原上下文,最终触发任务取消(Task Canceled)异常。

  2. 错误的并发实现
    原代码通过await Task.Run()在for循环中串行执行每个线程任务,完全没有实现多线程并发的压力测试效果——每个Task.Run必须等待上一个执行完成才会启动,无法达到压测目的。

  3. 潜在的线程安全问题
    虽然当前是串行执行,但如果后续改为并发,List<int>并非线程安全集合,多线程同时调用AddRange会导致数据损坏或异常。

修复后的代码

第一步:修正API调用方法为异步非阻塞

private async Task<int> CallApiAndGetStatusCodeAsync()
{
    try
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "some url");
        var responseResult = await httpClient.SendAsync(request);
        return (int)responseResult.StatusCode;
    }
    catch (Exception e)
    {
        logger.LogError(e, "Calling API failed");
        return -1; // 返回错误标识,避免编译报错
    }
}

第二步:实现真正的并发压力测试并安全聚合结果

private async Task DoWork()
{
    // 并行创建10个任务,每个任务内部串行执行50次API调用
    var concurrentTasks = Enumerable.Range(0, 10).Select(async _ =>
    {
        var taskResponses = new List<int>();
        for (int i = 0; i < 50; i++)
        {
            taskResponses.Add(await CallApiAndGetStatusCodeAsync());
        }
        return taskResponses;
    });

    // 等待所有并发任务完成,统一聚合结果
    var allResponseGroups = await Task.WhenAll(concurrentTasks);
    var allResponses = allResponseGroups.SelectMany(group => group).ToList();

    // 后续处理逻辑
}

额外优化建议

  • 调整连接数限制:默认HttpClient对单个域名的并发连接数限制为6,压测时可通过ServicePointManager.DefaultConnectionLimit = 100;(或更高值)调整,避免连接耗尽导致的请求失败。
  • 使用IHttpClientFactory:如果是.NET Core/.NET 5+项目,建议通过依赖注入使用IHttpClientFactory创建HttpClient,避免手动管理客户端实例带来的连接泄漏问题。

内容的提问来源于stack exchange,提问作者havij

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:13:35