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]}"; } } }
解决方案
问题根源
- 事件重复绑定:循环的每次迭代中重复绑定
DownloadFileCompleted和DownloadProgressChanged事件,导致同一事件被多次触发,进度条更新逻辑冲突。 - UI线程更新时机:
DownloadFileCompleted事件触发时,UI线程可能还在处理之前的进度更新,导致设置100%的操作被覆盖。 - 未等待UI渲染完成:设置Value为100后,未给UI线程足够时间完成渲染就开始下一个文件下载,视觉上无法显示完整的100%状态。
- 闭包陷阱:
DownloadFileCompleted事件中的i因闭包问题始终指向循环最后一个值,状态提示会出现错误。
修复步骤
- 将事件绑定移出循环,仅绑定一次,避免重复触发。
- 在下载下一个文件前,等待UI渲染完成,确保100%状态显示。
- 使用
Tag传递当前文件索引,解决闭包陷阱。 - 合并多个
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
相关产品推荐
相关产品推荐

