1
我有一些文件需要從ftp服務器下載。我想實現的是:以父母形式在控制上運行的事件
- 有一個
SplitContainer
,與上MainForm
面板之一ListView
。 - 我想獲得的文件列表,下載,創建一個
ProgressBar
並在ListView
- 每個文件在
ProgressChanged
事件Label
,我想上顯示的ProgressBar
和當前下載速度文件的當前進度在Label
這是我的代碼的最新版本:
internal async Task GetFiles(IEnumerable<string> urlList)
{
string dir = Environment.CurrentDirectory + "\\updates";
Directory.CreateDirectory(dir);
var tasks = new List<Task>();
foreach (var url in urlList)
tasks.Add(DownloadFile(url, dir));
await Task.WhenAll(tasks);
}
internal async Task DownloadFile(string url, string dir)
{
string filename = Helper.GetFilenameFromUrl(url);
ProgressBar pb = CreateFileDownloadBar();
Label lb = CreateFileDownloadLabel();
Stopwatch sw = new Stopwatch();
Helper.CrossThreadInvoke(_sender,() => _sender.listView1.Controls.Add(pb));
Helper.CrossThreadInvoke(_sender,() => _sender.listView1.Controls.Add(lb));
using (var client = new WebClient())
{
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, sw, pb, lb));
client.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) => Completed(sender, e, sw));
Helper.CrossThreadInvoke(_sender,() => _sender.lblFileDownload.Text = Helper.GetFilenameFromUrl(url));
await client.DownloadFileTaskAsync(url, string.Concat(dir, "\\", filename));
}
}
private Label CreateFileDownloadLabel()
{
Label lb = new Label()
{
Location = new System.Drawing.Point(_sender.offset - 180, 5 + offset)
};
return lb;
}
private ProgressBar CreateFileDownloadBar()
{
ProgressBar pb = new ProgressBar()
{
Location = new System.Drawing.Point(5, 5 + offset),
Size = new System.Drawing.Size(200, 20)
};
offset += pb.Height + 5;
return pb;
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e, Stopwatch sw, ProgressBar pb, Label lb)
{
pb.Value = e.ProgressPercentage;
lb.Text = string.Format("{0} kb/s", (e.BytesReceived/1024d/sw.Elapsed.TotalSeconds).ToString("0.00"));
}
然而,pb
和該事件中的不會更新MainForm
上的控件。我懷疑這是因爲我在本地複製它,而不是我添加到MainForm
,但我不知道如何使其工作。我是否需要某種計數器來CrossThreadInvoke
像
ProgressBar pb = Helper.CrossThreadInvoke(_sender,() => _sender.listView1.Controls[counter] as ProgressBar;
pb.Value = e.ProgressPercentage;
然而,這似乎不必要的複雜,所以我想知道是否有更好的方法。
添加'pb.Update()的想法;'設置新的值之後,看看是否這有助於 – lokusking
@lokusking不會,不幸的是, – Janushoff
我重讀了那個部分,你告訴你你的MainForm已經有了控件。當然,你必須更新這些控件,而不是你正在創建但不顯示的控件。你也可以反過來做。保持原有的代碼不變,從您的MainForm中移除控件,並將它們替換爲您在下載邏輯 – lokusking