WebClient.DownloadFileAsync - Download files one at a time

23,403

Solution 1

To simplify the task you can create separated attachment list:

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

where list is private field with type List<Attachment>. After this you should configure WebClient and start downloading of first file:

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

Your DownloadFileComplete handler should check if not all files already downloaded and call DownloadFileAsync again:

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

This code is not optimized solution. This is just idea.

Solution 2

At the risk of sounding like an idiot, this worked for me:

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

Where client is an instance of a WebClient object.

Share:
23,403
davebshow
Author by

davebshow

A previous script kiddie, now a drawer of boxes and arrows.

Updated on July 09, 2022

Comments

  • davebshow
    davebshow almost 2 years

    I am using the code below to download multiple attachments from a TFS server:

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

    I would like to download multiple files using DownloadFileAsync, but I want them to be downloaded one by one.

    One may ask "Why don't you just use the synchronous DownloadFile method?" Its because:

    1. I want to make use of the events provided by DownloadFileAsync.
    2. I don't want to make multiple instances of the Webclient to avoid flooding the server.

    This is the solution that I thought of:

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

    However, there are a couple of problems with this approach:

    1. The Thread.Sleep() is locking up my Form. I still need to make my own Thread or use BackgroundWorker. (I would like to avoid this as much as possible)
    2. The DownloadFileCompleted event is being triggered after ALL files has been downloaded. I don't know if this is a side-effect of using System.Threading.Thread.Sleep(1000);

    Is there a better approach to download files one at a time using WebClient.DownloadFileAsync?

    Thanks!

  • Max von Hippel
    Max von Hippel over 8 years
    I actually agree RE using Queue, but as Harshal said you should further explain what you're saying.
  • iam.Carrot
    iam.Carrot over 7 years
    Works pretty well (Y)
  • T.Todua
    T.Todua almost 4 years
    DON'T FORGET to use wc.Dispose() in the same scope after you get the response.