WebClient.DownloadFileAsync - Download files one at a time

asp.net, c#, download, multithreading, webclient

Solution

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.

Problem

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: - I want to make use of the events provided by DownloadFileAsync. - 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: - 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) - 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!

Original source