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

多线程下载场景下如何正确计算并展示实时下载速度(WPF)

WPF多线程批量下载实时显示Mbps速度解决方案

核心思路

  • 线程安全计数:用Interlocked类操作全局字节计数器,避免多线程并发修改导致的计数错误。
  • 定时采样计算:通过DispatcherTimer每秒采样一次累计下载字节数,计算这段时间的增量,转换成实时Mbps。
  • UI安全更新:利用DispatcherTimer在UI线程触发事件,直接更新UI控件,无需额外跨线程调度。

代码实现步骤

1. 定义窗口字段(全局计数器与计时器)

private long _totalBytesDownloaded = 0;
private long _lastBytesCount = 0;
private DispatcherTimer _speedTimer;

2. 初始化计时器(在窗口构造函数中)

public MainWindow()
{
    InitializeComponent();
    _speedTimer = new DispatcherTimer
    {
        Interval = TimeSpan.FromSeconds(1) // 每秒更新一次速度
    };
    _speedTimer.Tick += SpeedTimer_Tick;
}

3. 实现实时速度计算与UI更新

private void SpeedTimer_Tick(object sender, EventArgs e)
{
    // 线程安全读取当前累计字节数
    long currentBytes = Interlocked.Read(ref _totalBytesDownloaded);
    // 计算本次采样与上次的字节增量
    long bytesDelta = currentBytes - _lastBytesCount;
    _lastBytesCount = currentBytes;

    // 转换为Mbps:字节数转比特(×8)→ 转兆(÷1024÷1024)→ 除以时间间隔(秒)
    double realTimeMbps = (bytesDelta * 8.0) / 1024 / 1024 / _speedTimer.Interval.TotalSeconds;
    // 更新UI控件(假设你有一个名为txtRealTimeSpeed的TextBlock)
    txtRealTimeSpeed.Text = $"实时速度: {realTimeMbps:F2} Mbps";
}

4. 多线程下载逻辑(Parallel.ForEach)

private void btnStartDownload_Click(object sender, RoutedEventArgs e)
{
    // 重置计数器
    Interlocked.Exchange(ref _totalBytesDownloaded, 0);
    Interlocked.Exchange(ref _lastBytesCount, 0);
    _speedTimer.Start();

    // 替换为你的目标文件URL列表
    var downloadUrls = new List<string>
    {
        "https://example.com/file1.jpg",
        "https://example.com/file2.png",
        "https://example.com/file3.txt"
    };

    try
    {
        // 控制并行度,避免过多线程占用资源
        Parallel.ForEach(downloadUrls, new ParallelOptions { MaxDegreeOfParallelism = 6 }, url =>
        {
            // 复用HttpClient提升性能(HttpClient线程安全)
            using var client = new HttpClient();
            using var responseStream = client.GetStreamAsync(url).Result;
            // 替换为你的本地保存路径
            string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Path.GetFileName(url));
            using var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true);

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                fileStream.Write(buffer, 0, bytesRead);
                // 线程安全累加下载字节数
                Interlocked.Add(ref _totalBytesDownloaded, bytesRead);
            }
        });
    }
    catch (Exception ex)
    {
        MessageBox.Show($"下载异常: {ex.Message}");
    }
    finally
    {
        _speedTimer.Stop();
        txtRealTimeSpeed.Text = "下载完成";
    }
}

注意事项

  • 并行度设置:MaxDegreeOfParallelism建议根据网络情况调整,一般5-10即可,过多会导致网络拥堵反而降低速度。
  • HttpClient复用:如果下载任务多,建议全局复用一个HttpClient,而不是每次创建,减少资源消耗。
  • 缓冲区大小:示例中用8192字节,可根据文件大小调整,小文件用较小缓冲区也可以。
  • 异常处理:实际项目中建议细化异常捕获(比如网络超时、文件写入失败等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:15:37