如何使用webclient异步下载多个文件,但一次只能一个?

很难找到使用webclient类异步方法下载多个文件的代码示例,但一次下载一个。

如何启动异步下载,但要等到第一个完成,直到第二个,等等。基本上是一个问题。

(注意我不想使用同步方法,因为异步方法的function增加了。)

以下代码立即启动我的所有下载。 (进度条到处都是)

private void downloadFile(string url) { WebClient client = new WebClient(); client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged); client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted); // Starts the download btnGetDownload.Text = "Downloading..."; btnGetDownload.Enabled = false; progressBar1.Visible = true; lblFileName.Text = url; lblFileName.Visible = true; string FileName = url.Substring(url.LastIndexOf("/") + 1, (url.Length - url.LastIndexOf("/") - 1)); client.DownloadFileAsync(new Uri(url), "C:\\Test4\\" + FileName); } void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { } void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { double bytesIn = double.Parse(e.BytesReceived.ToString()); double totalBytes = double.Parse(e.TotalBytesToReceive.ToString()); double percentage = bytesIn / totalBytes * 100; progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); } 

我所做的是填充一个包含我所有url的队列,然后我下载队列中的每个项目。 当没有剩余物品时,我可以处理所有物品。 我在下面嘲笑了一些代码。 请记住,下面的代码用于下载字符串而不是文件。 修改下面的代码应该不会太难。

  private Queue _items = new Queue(); private List _results = new List(); private void PopulateItemsQueue() { _items.Enqueue("some_url_here"); _items.Enqueue("perhaps_another_here"); _items.Enqueue("and_a_third_item_as_well"); DownloadItem(); } private void DownloadItem() { if (_items.Any()) { var nextItem = _items.Dequeue(); var webClient = new WebClient(); webClient.DownloadStringCompleted += OnGetDownloadedStringCompleted; webClient.DownloadStringAsync(new Uri(nextItem)); return; } ProcessResults(_results); } private void OnGetDownloadedStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error == null && !string.IsNullOrEmpty(e.Result)) { // do something with e.Result string. _results.Add(e.Result); } DownloadItem(); } 

编辑:我已修改您的代码以使用队列。 不完全确定你希望如何进步。 我确定您是否希望进度能够满足所有下载需求,然后您可以将项目计数存储在’PopulateItemsQueue()’方法中,并在进度更改方法中使用该字段。

  private Queue _downloadUrls = new Queue(); private void downloadFile(IEnumerable urls) { foreach (var url in urls) { _downloadUrls.Enqueue(url); } // Starts the download btnGetDownload.Text = "Downloading..."; btnGetDownload.Enabled = false; progressBar1.Visible = true; lblFileName.Visible = true; DownloadFile(); } private void DownloadFile() { if (_downloadUrls.Any()) { WebClient client = new WebClient(); client.DownloadProgressChanged += client_DownloadProgressChanged; client.DownloadFileCompleted += client_DownloadFileCompleted; var url = _downloadUrls.Dequeue(); string FileName = url.Substring(url.LastIndexOf("/") + 1, (url.Length - url.LastIndexOf("/") - 1)); client.DownloadFileAsync(new Uri(url), "C:\\Test4\\" + FileName); lblFileName.Text = url; return; } // End of the download btnGetDownload.Text = "Download Complete"; } private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { if (e.Error != null) { // handle error scenario throw e.Error; } if (e.Cancelled) { // handle cancelled scenario } DownloadFile(); } void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { double bytesIn = double.Parse(e.BytesReceived.ToString()); double totalBytes = double.Parse(e.TotalBytesToReceive.ToString()); double percentage = bytesIn / totalBytes * 100; progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); } 

我很难理解问题所在。 如果你只为第一个文件调用异步方法,它不会只下载该文件吗? 为什么不使用client_downlaodFileCompleted事件根据AsyncCompletedEvents传递的某个值启动下一个文件下载,或者将下载的文件列表保存为静态变量,并使用client_DownloadFileCompleted迭代列表以查找要下载的下一个文件。

希望有所帮助,但如果我误解了您的问题,请发布更多信息。

我会创建一个新方法,例如名为getUrlFromQueue,它从队列(集合或数组)返回一个新url并删除它..然后它调用downloadFile(url) – 并在client_DownloadFileCompleted中再次调用getUrlFromQueue。