如何单独更新进度条(同时下载)
本文关键字:下载 何单独 更新 | 更新日期: 2023-09-27 18:36:28
我目前正在尝试向我的应用程序添加并行下载,但我不知道如何处理 DownloadProgressChangedEvent 以在多个进度条中显示进度。
我正在使用一个数据网格视图,其中包含用户能够下载的每个文件的预定义行,并且每行都有一个带有进度条的单元格。
现在的问题是,我不知道如何单独更新每个进度条,因为现在,所有选定的进度条都显示相同的百分比,它们只是在download1和download2的进度之间跳跃。
这是我使用的代码:
要开始下载:
private void download_button_Click(object sender, EventArgs e)
{
start = DateTime.Now;
download_button.Enabled = false;
Rows = dataGridView1.Rows.Count;
Checked = 0;
CheckedCount = 0;
//count the selected rows
for (i = 0; i < Rows; i++)
{
Checked = Convert.ToInt32(dataGridView1.Rows[i].Cells["checkboxcol"].FormattedValue);
CheckedCount += Checked;
richTextBox3.Text = CheckedCount.ToString();
}
for (int z = 1; z < CheckedCount; z++)
{
_MultipleWebClients = new WebClient();
_MultipleWebClients.DownloadFileCompleted += new AsyncCompletedEventHandler(_DownloadFileCompleted);
_MultipleWebClients.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(_DownloadProgressChanged);
_MultipleWebClients.DownloadFileAsync(new Uri(_downloadUrlList[z].ToString()), @"F:'test" + z + ".mp4");
}
}
(我也无法同时下载两个以上的文件 - 在前两个完成之前,第三次下载不会开始)
下载进度更改事件:
private void _DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
for (int c = 0; c < CheckedCount; c++)
{
dataGridView1.Rows[_downloadRowNrList[c]].Cells[3].Value = e.ProgressPercentage;
}
float size = ((e.TotalBytesToReceive / 1024) / 1024);
label1.Text = size.ToString();
double dn = (double)e.BytesReceived / 1024.0 / (DateTime.Now - start).TotalSeconds;
label2.Text = (dn.ToString("n") + " KB/s) " + e.ProgressPercentage);
}
问题可能是,所有进度条都使用相同的下载进度更改事件,但我不确定如何在不知道所需数量的情况下创建多个这些事件......
所以我希望有人能够帮助我,
提前感谢!
您要做的是使用其他DownloadFileAsync
方法:http://msdn.microsoft.com/en-us/library/ms144197.aspx
第三个参数是 userToken,它作为DownloadProgressChangedEventArgs
的一部分传递(它位于 UserState
属性中)。
因此,当您进行DownloadFileAsync
调用时,传入一个唯一令牌(整数或其他内容),然后可以将其与需要更新的进度栏相关联。
//(Snip)
//in download_button_Click, pass the row you are updating to the event.
for (int z = 1; z < CheckedCount; z++)
{
_MultipleWebClients = new WebClient();
_MultipleWebClients.DownloadFileCompleted += new AsyncCompletedEventHandler(_DownloadFileCompleted);
_MultipleWebClients.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(_DownloadProgressChanged);
_MultipleWebClients.DownloadFileAsync(new Uri(_downloadUrlList[z].ToString()), @"F:'test" + z + ".mp4", dataGridView1.Rows[z]);
}
}
private void _DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
var rowToUpdate = (DataGridViewRow)e.UserState;
RowToUpdate["ProgressBar"].Value = e.ProgressPercentage;
RowToUpdate["TextProgress"].Value = e.ProgressPercentage;
RowToUpdate["BytesToRecive"].Value = ((e.TotalBytesToReceive / 1024) / 1024).ToString();
double dn = (double)e.BytesReceived / 1024.0 / (DateTime.Now - start).TotalSeconds;
RowToUpdate["Speed"].Value = (dn.ToString("n") + " KB/s) " + e.ProgressPercentage);
}
听起来你需要一个进度条来进行多部分进度:
public partial class ProgressBarEx : ProgressBar
{
private readonly Dictionary<Guid, double> _partsProgress =
new Dictionary<Guid, double>();
private readonly Dictionary<Guid, double> _partsSizes =
new Dictionary<Guid, double>();
private double _value;
private double _maximum;
public ProgressBarEx()
{
this.InitializeComponent();
}
public int Parts
{
get { return this._partsSizes.Count; }
}
public new int Minimum { get; private set; }
public new double Maximum
{
get { return this._maximum; }
private set
{
this._maximum = value;
base.Maximum = (int)value;
}
}
public new double Value
{
get { return this._value; }
private set
{
this._value = value;
base.Value = (int)value;
}
}
[Obsolete("Not useable in ProgressBarEx.")]
public new int Step
{
get { return 0; }
}
public Guid AddPart(double size)
{
if (size <= 0)
{
throw new ArgumentException("size");
}
var partId = Guid.NewGuid();
this.Maximum += size;
this._partsSizes.Add(partId, size);
this._partsProgress.Add(partId, 0);
return partId;
}
public bool RemovePart(Guid partId)
{
double size;
if (!this._partsSizes.TryGetValue(partId, out size))
{
return false;
}
this.Maximum -= size;
this._partsSizes.Remove(partId);
this.Value -= this._partsProgress[partId];
this._partsProgress.Remove(partId);
return true;
}
public bool ContainsPart(Guid partId)
{
return this._partsSizes.ContainsKey(partId);
}
public double GetProgress(Guid partId)
{
return this._partsProgress[partId];
}
public void SetProgress(Guid partId, double progress)
{
if (progress < 0 || this._partsSizes[partId] < progress)
{
throw new ArgumentOutOfRangeException("progress");
}
this.Value += progress - this._partsProgress[partId];
this._partsProgress[partId] = progress;
}
public void AddProgress(Guid partId, double progress)
{
this.SetProgress(partId, progress + this._partsProgress[partId]);
}
[Obsolete("Not useable in ProgressBarEx.")]
public new void PerformStep()
{
}
}
用法示例:
public Form1()
{
InitializeComponent();
var pbe = new ProgressBarEx {Location = new Point(100, 100)};
this.Controls.Add(pbe);
for (var i = 0; i < 4; i++)
{
var size = i * 10 + 30;
var partId = pbe.AddPart(size);
var pb = new ProgressBar
{
Maximum = size,
Location = new Point(100, i * 30 + 130)
};
this.Controls.Add(pb);
var timer = new Timer {Interval = 1000 + i * 100};
timer.Tick += (sender, args) =>
{
pb.Value += 5;
pbe.AddProgress(partId, 5);
if (pb.Value == pb.Maximum)
{
timer.Stop();
}
};
timer.Start();
}
}