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!
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 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.
Method 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.
Method 3
I think that should use Queue
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0