WebClient.DownloadFileAsync - загрузка файлов по одному - PullRequest
6 голосов
/ 11 января 2010

Я использую приведенный ниже код для загрузки нескольких вложений с сервера TFS:

foreach (Attachment a in wi.Attachments)
{    
    WebClient wc = new WebClient();
    wc.Credentials = (ICredentials)netCred;
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(a.Uri, "C:\\" + a.Name);
}

Я хочу загрузить несколько файлов с помощью DownloadFileAsync, но я хочу, чтобы они загружались по одному.

Кто-то может спросить: «Почему бы вам просто не использовать синхронный метод DownloadFile?» Это потому что:

  1. Я хочу использовать события, предоставляемые DownloadFileAsync.
  2. Я не хочу создавать несколько экземпляров Web-клиента, чтобы избежать переполнения сервера.

Это решение, о котором я подумал:

foreach (Attachment a in wi.Attachments)
{        
    WebClient wc = new WebClient();
    wc.Credentials = (ICredentials)netCred;
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(a.Uri, "C:\\" + a.Name);
    while (wc.IsBusy)
    {
        System.Threading.Thread.Sleep(1000);
    }
}

Однако у этого подхода есть пара проблем:

  1. Thread.Sleep () блокирует мою форму. Мне все еще нужно сделать свой собственный поток или использовать BackgroundWorker. (Я хотел бы избежать этого в максимально возможной степени)
  2. Событие DownloadFileCompleted запускается после загрузки ALL файлов. Я не знаю, является ли это побочным эффектом использования System.Threading.Thread.Sleep (1000);

Есть ли лучший подход для загрузки файлов по одному с помощью WebClient.DownloadFileAsync?

Спасибо!

Ответы [ 3 ]

8 голосов
/ 11 января 2010

Для упрощения задачи вы можете создать отдельный список вложений:

list = new List<Attachment>(wi.Attachments);

, где list - приватное поле с типом List . После этого вы должны настроить WebClient и начать загрузку первого файла:

if (list.Count > 0) {
   WebClient wc = new WebClient();
   wc.Credentials = (ICredentials)netCred;
   wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
   wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name);
}

Ваш обработчик DownloadFileComplete должен проверить, все ли файлы уже загружены, и снова вызвать DownloadFileAsync:

void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) {
   // ... do something useful 
   list.RemoveAt(0);
   if (list.Count > 0)
      wc.DownloadFileAsync(list[0].Uri, @"C:\" + list[0].Name);
}

Этот код не является оптимизированным решением. Это просто идея.

2 голосов
/ 16 января 2014

С риском звучать как идиот, это сработало для меня:

Console.WriteLine("Downloading...");
client.DownloadFileAsync(new Uri(file.Value), filePath);
while (client.IsBusy)
{
    // run some stuff like checking download progress etc
}
Console.WriteLine("Done. {0}", filePath);

Где client - это экземпляр объекта WebClient.

0 голосов
/ 01 августа 2010

Я думаю, что следует использовать очередь

...