We help IT Professionals succeed at work.

DownloadFileAsync One File at a Time

Medium Priority
Last Modified: 2013-12-17
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.
Watch Question

Distinguished Expert 2017
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?



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...");


Fernando - I was able to implement a work-around... Thanks for the help though!
Fernando SotoRetired
Distinguished Expert 2017

Not a problem, glad you got through the situation. ;=)


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