Come posso scaricare Async più file utilizzando webclient, ma uno alla volta?

È stato sorprendentemente difficile trovare un esempio di codice per il download di più file utilizzando il metodo asincrono della class webclient, ma scaricandone uno alla volta.

Come posso iniziare un download asincrono, ma attendi fino a quando il primo è finito fino al secondo, ecc. Fondamentalmente un que.

(nota che non voglio usare il metodo sync, a causa della maggiore funzionalità del metodo asincrono).

Il codice seguente avvia tutti i miei download contemporaneamente. (la barra di avanzamento è dappertutto)

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()); } 

Quello che ho fatto è compilare una coda che contiene tutti i miei url, quindi scarico ogni elemento in coda. Quando non ci sono più oggetti, posso quindi elaborare tutti gli articoli. Ho deriso qualche codice in basso. Tieni presente che il codice seguente serve per scaricare stringhe e non file. Non dovrebbe essere troppo difficile modificare il codice sottostante.

  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(); } 

Modifica: ho modificato il codice per utilizzare una coda. Non del tutto sicuro di come volevi che i progressi funzionassero. Sono certo che se si desidera che i progressi siano soddisfatti per tutti i download, è ansible memorizzare il conteggio articoli nel metodo ‘PopulateItemsQueue ()’ e utilizzare tale campo nel metodo di avanzamento modificato.

  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()); } 

Sto facendo fatica a capire dove si trova il problema. Se chiami solo il metodo asincrono per il primo file, non scaricherà solo quel file? Perché non utilizzare l’evento client_downlaodFileCompleted per avviare il download del file successivo in base a un valore passato da AsyncCompletedEvents, o mantenere un elenco di file scaricati come variabile statica e avere l’elenco iterato client_DownloadFileCompleted per trovare il prossimo file da scaricare.

Spero che ti aiuti ma per favore pubblica più informazioni se ho superato la tua domanda.

Vorrei creare un nuovo metodo, ad esempio chiamato getUrlFromQueue che mi restituisce un nuovo url dalla coda (raccolta o array) e lo elimina .. quindi chiama downloadFile (url) – e in client_DownloadFileCompleted chiamo di nuovo getUrlFromQueue.