Alex
Alex

Reputation: 36111

How can I download several files from the iInternet and wait for everyone to download?

I need to download several HTML files in my ASP.NET application. The average file size is about 100 KB.

Right now I'm using the following code.

    foreach (var item in items)
    {
        string url = (string)item.Element("link");
        string title = (string)item.Element("title");
        string fileName = Server.MapPath(title + ".html");

        // Add the attachement
        WebClient client = new WebClient();
        client.Encoding = System.Text.Encoding.UTF8;
        client.DownloadFileCompleted += new AsyncCompletedEventHandler((a, b) =>
        {
            System.Threading.Thread.Sleep(2000);
            message.Attachments.Add(new Attachment(fileName));
            counter++;

            // If we've downloaded all the items, send the message with the items attached to it
            if (counter == totalItems)
            {
                SendMessage(message);
            }
        });
        client.DownloadFileAsync(new Uri(url), fileName); 
    }

As you can see I'm downloading the files asynchronously, but the foreach loop doesn't care that the file hasn't been downloaded yet, it goes to the next iterated item.

As a result of this, some of the files are not downloaded.

Upvotes: 0

Views: 172

Answers (3)

Babak Naffas
Babak Naffas

Reputation: 12561

It could as simple as a bug in your code to populate totalItems.

Try if (counter == items.Count()) instead of if (counter == totalItems)

Upvotes: 0

dtb
dtb

Reputation: 217293

Use the CountdownEvent Class to count down the number of remaining files.

var cde = new CountdownEvent(items.Count);

foreach (var item in items)
{
    ...

    client.DownloadFileCompleted += (a, b) =>
    {
        lock (message)
        {
            message.Attachments.Add(new Attachment(fileName));
            cde.AddCount();
        }
    };

    ...
}

// If we've downloaded all the items,
// send the message with the items attached to it
cde.Wait();
lock (message)
{
    SendMessage(message);
}

Upvotes: 3

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56162

If you're using .NET Framework 4 you could use Task class and WaitAll method.

Upvotes: 2

Related Questions