views:

992

answers:

2

Hello All,

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!

+1  A: 

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.

Andrey Shvydky
A: 

I think that should use Queue

heavenwing