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

ProgressBarEx1进度条绿色填充无法达到100%的问题求助

C# WinForms文件下载进度条显示异常问题

问题描述

使用C# WinForms开发文件下载功能时遇到以下异常:

  • 单个文件下载完成后,ProgressBarEx1的Value已设为100%,但进度条内的绿色填充始终无法到达末端;仅当所有文件全部下载完成时,绿色填充才会显示100%。
  • 期望单个文件下载完成时,绿色填充能平滑过渡到100%,再开始下一个文件的下载进度更新。
  • 尝试在DownloadFileCompleted事件中设置progressBarEx1.Value = 100,效果不佳;使用Thread.Sleep也无法解决,进度条内的百分比有时显示99%或更低,偶尔显示100%但绿色仍未拉满。
  • 断点查看发现下载完成时Value确实为100%,但界面未正确显示。文件下载功能正常,文件已成功保存到硬盘。

相关代码片段

client.DownloadFileCompleted += (s, e) =>
{
    lblStatus.Text = $"Status: Download of file {i + 1}/{totalFiles} completed.";
    progressBarEx1.Value = 100;
};

完整代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Download_Files
{
    public partial class Form1 : Form
    {
        List<string> links = new List<string>
        {
            "https://hil-speed.hetzner.com/100MB.bin",
            "https://hil-speed.hetzner.com/100MB.bin",
            "https://hil-speed.hetzner.com/100MB.bin",
            // Add more URLs as needed
        };

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private async Task DownloadAsync()
        {
            using (var client = new WebClient())
            {
                int totalFiles = links.Count;

                for (int i = 0; i < totalFiles; i++)
                {
                    var currentFile = links[i];
                    var destinationPath = $@"d:\testfiles\100MB{i}.bin";

                    client.DownloadFileCompleted += (s, e) =>
                    {
                        lblStatus.Text = $"Status: Download of file {i + 1}/{totalFiles} completed.";
                        progressBarEx1.Value = 100;
                    };

                    client.DownloadProgressChanged += (s, e) => progressBarEx1.Value = e.ProgressPercentage;
                    client.DownloadProgressChanged += (s, e) => lblDownloadInfo.Text = "Download Info: " + FormatBytes(e.BytesReceived);
                    client.DownloadProgressChanged += (s, e) =>
                    {
                        
                    };

                    await client.DownloadFileTaskAsync(new Uri(currentFile), destinationPath);
                }
            }
        }

        private async void btnDownload_Click(object sender, EventArgs e)
        {
            await DownloadAsync();
        }

        public static string FormatBytes(long bytes)
        {
            const int scale = 1024;
            string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };

            int magnitude = (int)Math.Floor(Math.Log(bytes, scale));

            double adjustedSize = bytes / Math.Pow(scale, magnitude);
            string format = (magnitude > 0 && magnitude < 3) ? "F2" : "F0"; // Show two decimal places for KB and MB, no decimals for others

            return $"{adjustedSize.ToString(format)} {units[magnitude]}";
        }
    }
}

解决方案

问题根源

  1. 事件重复绑定:循环的每次迭代中重复绑定DownloadFileCompleted和DownloadProgressChanged事件,导致同一事件被多次触发,进度条更新逻辑冲突。
  2. UI线程更新时机:DownloadFileCompleted事件触发时,UI线程可能还在处理之前的进度更新,导致设置100%的操作被覆盖。
  3. 未等待UI渲染完成:设置Value为100后,未给UI线程足够时间完成渲染就开始下一个文件下载,视觉上无法显示完整的100%状态。
  4. 闭包陷阱:DownloadFileCompleted事件中的i因闭包问题始终指向循环最后一个值,状态提示会出现错误。

修复步骤

  1. 将事件绑定移出循环,仅绑定一次,避免重复触发。
  2. 在下载下一个文件前,等待UI渲染完成,确保100%状态显示。
  3. 使用Tag传递当前文件索引,解决闭包陷阱。
  4. 合并多个DownloadProgressChanged事件处理,减少冗余触发。

修复后的代码

private async Task DownloadAsync()
{
    using (var client = new WebClient())
    {
        int totalFiles = links.Count;

        // 仅绑定一次事件
        client.DownloadProgressChanged += (s, e) => 
        {
            progressBarEx1.Value = e.ProgressPercentage;
            lblDownloadInfo.Text = "Download Info: " + FormatBytes(e.BytesReceived);
        };

        client.DownloadFileCompleted += (s, e) =>
        {
            int currentIndex = (int)((WebClient)s).Tag;
            lblStatus.Text = $"Status: Download of file {currentIndex + 1}/{totalFiles} completed.";
            progressBarEx1.Value = 100;
            progressBarEx1.Refresh(); // 强制控件重绘,确保100%状态显示
        };

        for (int i = 0; i < totalFiles; i++)
        {
            var currentFile = links[i];
            var destinationPath = $@"d:\testfiles\100MB{i}.bin";

            // 传递当前文件索引,解决闭包问题
            client.Tag = i;

            await client.DownloadFileTaskAsync(new Uri(currentFile), destinationPath);
            
            // 等待UI渲染完成,再进行下一个文件下载
            await Task.Delay(200);
            
            // 重置进度条为0,准备下一个文件
            progressBarEx1.Value = 0;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:01:04