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

如何在C#的Task.WhenAll方法中统计每个HTTP请求的耗时

实现每个HTTP请求的耗时统计方案

首先要修正原代码的一个关键问题:每次调用GetRequest都新建HttpClient会耗尽套接字资源,因为HttpClient的连接池与实例绑定,频繁创建会造成资源浪费甚至触发异常,必须复用HttpClient实例。

接下来是耗时统计的具体实现,核心思路是为每个请求单独记录起始/结束时间,同时关联请求标识(比如你的循环索引),方便对应到具体请求:

1. 定义结果存储类型(可选但推荐)

用来统一保存请求标识、耗时和响应结果:

public class RequestTimingResult
{
    public int RequestIndex { get; set; }
    public TimeSpan ElapsedTime { get; set; }
    public HttpResponseMessage Response { get; set; }
}

2. 修改请求执行与统计逻辑

public static async Task Start()
{
    // 复用同一个HttpClient实例
    using var httpClient = new HttpClient();
    var tasks = new List<Task<RequestTimingResult>>();

    for (int i = 0; i < 10; i++)
    {
        // 捕获循环变量,避免闭包引用问题
        int requestIndex = i;
        
        var task = Task.Run(async () =>
        {
            // 启动计时器
            var stopwatch = Stopwatch.StartNew();
            
            // 执行请求
            var response = await httpClient.GetAsync($"https://address.com?p={requestIndex}");
            
            // 停止计时并计算耗时
            stopwatch.Stop();
            
            return new RequestTimingResult
            {
                RequestIndex = requestIndex,
                ElapsedTime = stopwatch.Elapsed,
                Response = response
            };
        });
        
        tasks.Add(task);
    }

    // 等待所有请求完成
    var allResults = await Task.WhenAll(tasks);

    // 输出每个请求的耗时统计
    foreach (var result in allResults)
    {
        Console.WriteLine($"请求 {result.RequestIndex}:耗时 {result.ElapsedTime.TotalMilliseconds:F2} 毫秒,响应状态码 {result.Response.StatusCode}");
    }
}

关键细节说明

  • 复用HttpClient:用using包裹确保资源正确释放,同时整个循环复用同一个实例,避免套接字耗尽问题。
  • 闭包问题处理:循环内创建requestIndex变量捕获当前循环值,否则所有任务会引用同一个循环变量,导致最终拿到的都是最后一个索引值。
  • 精确计时:使用Stopwatch类计时,精度远高于DateTime,适合统计短时间操作的耗时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:30:11