Как Async загружает несколько файлов с помощью webclient, но по одному?

Неожиданно трудно найти пример кода для загрузки нескольких файлов с использованием асинхронного метода classа webclient, но загрузка по одному.

Как я могу инициировать асинхронную загрузку, но дождитесь, пока первая не будет закончена до второй, и т. Д. В принципе, очередь.

(обратите внимание, что я не хочу использовать метод синхронизации из-за повышенной функциональности метода async.)

Следующий код запускает все мои загрузки сразу. (индикатор прогресса повсюду)

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

Я изо всех сил пытаюсь понять, в чем проблема. Если вы вызываете только метод async для первого файла, не будет ли он загружать только этот файл? Почему бы не использовать событие client_downlaodFileCompleted для запуска следующей загрузки файла на основе некоторого значения, переданного AsyncCompletedEvents, или сохранить список загруженных файлов в качестве статической переменной и иметь client_DownloadFileCompleted итерацию списка tht для поиска следующего загружаемого файла.

Надеюсь, что это поможет, но, пожалуйста, напишите больше информации, если я выяснил ваш вопрос.

Я бы сделал новый метод, например, с именем getUrlFromQueue, который возвращает мне новый url из очереди (коллекции или массива) и удаляет его. Затем он вызывает downloadFile (url) – и в client_DownloadFileCompleted снова вызываю getUrlFromQueue.

Interesting Posts
Давайте будем гением компьютера.