2017-03-08 47 views
1

我有一些文件需要從ftp服務器下載。我想實現的是:以父母形式在控制上運行的事件

  1. 有一個SplitContainer,與上MainForm面板之一ListView
  2. 我想獲得的文件列表,下載,創建一個ProgressBar並在ListView
  3. 每個文件在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; 

然而,這似乎不必要的複雜,所以我想知道是否有更好的方法。

+0

添加'pb.Update()的想法;'設置新的值之後,看看是否這有助於 – lokusking

+0

@lokusking不會,不幸的是, – Janushoff

+0

我重讀了那個部分,你告訴你你的MainForm已經有了控件。當然,你必須更新這些控件,而不是你正在創建但不顯示的控件。你也可以反過來做。保持原有的代碼不變,從您的MainForm中移除控件,並將它們替換爲您在下載邏輯 – lokusking

回答

0

我給你做了一個很小的例子,它實際上並不漂亮,但應該給你一個想法如何實現進展的東西。

另外我已經評論了很多東西,並插入了一些演示代碼。

關鍵是要使用Controls.Invoke() - 方法,如果你在不同的線程/任務。

public partial class Form1 : Form { 


    public Form1() { 

     InitializeComponent(); 
     var l = new List<string>(); 
     for (int i = 0; i < 10; i++) { 
     l.Add("Some Text" + i); 
     } 
     Task.Factory.StartNew(async() => { 
     await GetFiles(l, this); 
     }); 
    } 



    private int ctrlCount = 0; 

    public void AddControlToListView(Control c) { 
     if (c is Label) { 
     c.Location = new Point(205, ctrlCount * c.Height + 5); 
     } else { 
     c.Location = new Point(5, ctrlCount * c.Height + 5); 
     } 

     if (this.listView1.InvokeRequired) { 
     this.listView1.Invoke(new Action<Control>(this.listView1.Controls.Add), c); 
     this.listView1.Invoke(new Action(this.listView1.Update)); 
     } else { 
     this.listView1.Controls.Add(c); 
     this.listView1.Update(); 
     } 

     ctrlCount++; 
    } 

    internal async Task GetFiles(IEnumerable<string> urlList, Form1 parent) { 
     //string dir = Environment.CurrentDirectory + "\\updates"; 

     //Directory.CreateDirectory(dir); 
     var tasks = new List<Task>(); 

     foreach (var url in urlList) 
     tasks.Add(DownloadFile(url, "")); 

     await Task.WhenAll(tasks); 
    } 



    internal async Task DownloadFile(string url, string dir) { 
     string filename = "";// Helper.GetFilenameFromUrl(url); 
     ProgressBar pb = CreateFileDownloadBar(); 
     Label lb = CreateFileDownloadLabel(); 
     this.AddControlToListView(pb); 
     this.AddControlToListView(lb); 
     Stopwatch sw = new Stopwatch(); 
     //Helper.CrossThreadInvoke(_sender,() => _sender.listView1.Controls.Add(pb)); 
     //Helper.CrossThreadInvoke(_sender,() => _sender.listView1.Controls.Add(lb)); 
     await Task.Factory.StartNew(() => { 
     for (int i = 1; i < 11; i++) { 
      pb.Invoke(new MethodInvoker(delegate { 
      pb.Value = i * 10; 
      })); 
      lb.Invoke(new MethodInvoker(delegate { 
      lb.Text = (i * 10).ToString(); 
      })); 
      Thread.Sleep(500); 
     } 
     }); 
     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() { 
     Text = "Hello" 
     //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")); 
    } 

} 

我希望這給你如何創建和更新您的ProgressBars