WebClient.DownloadFileAsync - Download files one at a time

青春壹個敷衍的年華 提交于 2019-12-17 15:59:08

问题


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:


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.




回答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.




回答3:


I think that should use Queue



来源:https://stackoverflow.com/questions/2042258/webclient-downloadfileasync-download-files-one-at-a-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!