如何使用C# WebClient组件计算并实时显示文件下载速度
实时下载速度实现方案
WebClient的DownloadProgressChangedEventArgs未提供现成的下载速度属性,需要通过两次进度回调的差值自行计算,实现步骤如下:
1. 窗体类新增成员变量
用来记录上一次统计的字节数和时间戳,代码放在窗体类的成员定义位置,不要写在Download方法内部:
private long _lastReceivedBytes = 0; private DateTime _lastUpdateTime = DateTime.Now;
2. 修改Download方法的对应逻辑
先初始化统计变量,再替换未完成的label4赋值逻辑,完整修改后的代码如下:
private void Download() { // 每次启动下载前重置统计变量 _lastReceivedBytes = 0; _lastUpdateTime = DateTime.Now; using (var client = new WebClient()) { client.DownloadFileCompleted += (s, e) => label1.Text = "Download file completed."; client.DownloadProgressChanged += (s, e) => progressBar1.Value = e.ProgressPercentage; client.DownloadProgressChanged += (s, e) => label2.Text = FormatBytes(e.BytesReceived); // 替换原来未完成的label4赋值行 client.DownloadProgressChanged += (s, e) => { TimeSpan timeDiff = DateTime.Now - _lastUpdateTime; // 避免时间差过小导致速度计算波动过大,至少间隔100ms更新一次 if (timeDiff.TotalMilliseconds >= 100) { long bytesDiff = e.BytesReceived - _lastReceivedBytes; double speed = bytesDiff / timeDiff.TotalSeconds; label4.Text = $"{FormatBytes(Convert.ToInt64(speed))}/s"; // 更新统计变量 _lastReceivedBytes = e.BytesReceived; _lastUpdateTime = DateTime.Now; } }; client.DownloadProgressChanged += (s, e) => { label3.Text = "%" + e.ProgressPercentage.ToString(); label3.Left = Math.Min( (int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width), progressBar1.Width - label3.Width ); }; client.DownloadFileAsync(new Uri("https://speed.hetzner.de/10GB.bin"), @"d:\10GB.bin"); } }
逻辑说明
- 每次进度回调触发时,计算当前时间和上次统计时间的差值,以及当前收到的字节数和上次统计字节数的差值
- 速度=字节差值/时间差值(单位:字节/秒)
- 复用代码中已有的
FormatBytes方法将速度格式化为易读的KB/s、MB/s等单位 DownloadProgressChanged事件默认在UI线程触发,无需额外做线程安全处理就可以直接给控件赋值
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

