DownloadFileAsync One File at a Time

i'm using WebClient and DownloadFileAsync to download files. I'm looping thru a file listing, and calling "DownloadFileAsync(url, file)" each time thru the loop. I have it wired to events which update a progress bar and shows the file download progress. I want the loop to stop/pause while the DownloadFileAsync method downloads the first file called from the loop...once that file is completely downloaded, i then want the loop to move on to the next file.

The main problem is that it loops thru multiple times before the first download is finished, and my progress bar status starts "jumping" back and forth between the two files that are being downloaded simultaneously. I tried using the "DownloadFile" method instead of "DownloadFileAsync", but for some reason it will not trigger my DownloadProgressChangedEvent event.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Fernando SotoRetiredCommented:
Hi friskyweasel;

The DownloadFileAsync is a non blocking method call. which means that as soon as the call is made it will continue in the loop giving you multiple downloads at the same time. The DownloadFile is a blocking call and so the current thread stops processing until the download has completed or throws an error. The DownloadFile does not have a callback functionality because it is a blocking call and you will know when it comes back from processing the download.

The way I see it is you have two options. 1)  Use DownloadFile in a loop and when it come back from downloading the file adjust the progress bar right after the call to DownloadFile and use a DoEvents call to update the user interface and let the loop continue in this way until all files have been downloaded. This option is not a very good one because as the files are downloading the UI will be unresponsive.  2)
You can use a separate thread and use the DownloadFile call and when the download is completed update the progress bar and continue. This will free up the UI for other user request.

Can you  post the code that is doing the downloads and I may be able to put some sample code together?


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
friskyweaselAuthor Commented:
thanks a lot for the help Fernando - ok so here's what i have in a nutshell (code needs to be cleaned up, but i wanted to get something working first)

one note - your comment above sounds like you're talking about updating the progress bar each time a file completes downloading, and show progress based on "X files out of Y Total" have downloaded so far. what i'd actually like to do is have my progress bar show "X percent of Current File downloaded"....

i have a listbox with all files in it (the files i'm looping through)...i want to highlight the currently downloading file in the listbox, and have the single progress bar show that file's progress....once that file is downloaded, i'm going to move to the next file in the listbox and start the process all over

here is the method that i call from within the loop: GetFile(url, filename);
(prgDownload = the name of my progress bar)

        private void GetFile(string PassedURL, string PassedFilename)
            PassedFilename = Application.StartupPath + "\\files\\" + PassedFilename;
            this.prgDownload.Maximum = 100;
            WebClient wc = new WebClient();
            Uri url = new Uri(PassedURL);

            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback);
            wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallBack2);
            wc.DownloadFileAsync(url, PassedFilename);

        private void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e)
            this.prgDownload.Value = e.ProgressPercentage;
            this.lblSize.Text = "Total Size: " + (e.TotalBytesToReceive / 1048576).ToString() + "MB";
            this.lblReceived.Text = "Bytes Received: " + (e.BytesReceived / 1048576).ToString() + "MB";
            this.lblPercent.Text = "Progress Percentage: " + e.ProgressPercentage.ToString();
        private void DownloadFileCallBack2(object sender, AsyncCompletedEventArgs c)
            //MessageBox.Show("Download finished...");

friskyweaselAuthor Commented:
Fernando - I was able to implement a work-around... Thanks for the help though!
Fernando SotoRetiredCommented:
Not a problem, glad you got through the situation. ;=)
friskyweaselAuthor Commented:
in case anyone else comes across this, here's what i did in a nutshell...i was originally calling the "GetFile()" method from within a loop - it was being called over and over and firing "GetFile", and consequently, "wc.DownloadFileAsync(url, PassedFilename);" multiple times, which was creating multiple download sessions and causing my progress bar to jump all over the place (different progress percentages for different unique downloads)

the fix was really just a hack, but it worked - in a nutshell i did the following logic:
added all my desired files (URL's) into a listbox...then determined a color (green) that i would use for each listbox row to designate the the file was successfully downloaded

i loop through the listbox, and ignore any entries for which the current row color is green...if it's not green then i call "GetFile()" in the loop, and the line of code immediately after "GetFile()" is a "break;" to stop the looping...

I then placed some code in the " DownloadFileCallBack2" which sets the current listbox entry's row color to green, and calls my loop function all over again.... like i said - kind of hacky - but for quick and dirty it works

FernandoSoto - for your excellent explanation of the issue, i'll award you the points
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.