How can I download multiple files from a List using webclient async ? getting exception System.NotSupportedException: 'WebClient does not support concurrent I/O operations.'

sharon glipman 441 Reputation points
2021-10-10T20:28:28.707+00:00
private void Download()
        {
            using (var client = new WebClient())
            {
                client.DownloadFileCompleted += (s, e) => label1.Text = "Download file completed.";
                client.DownloadProgressChanged += (s, e) => progressBar1.Value = e.ProgressPercentage;
                client.DownloadProgressChanged += (s, e) => label2.Text = FormatBytes(e.BytesReceived);
                client.DownloadProgressChanged += (s, e) =>
                {
                    label3.Text = "%" + e.ProgressPercentage.ToString();
                    label3.Left = Math.Min(
                        (int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width),
                        progressBar1.Width - label3.Width
                    );                   
                };

                for (int i = 0; i < urls.Count; i++)
                {
                    client.DownloadFileAsync(new Uri(urls[i]), @"d:\Images\img" + i + ".jpg");
                }
            }
        }

The exception is on the line :

for (int i = 0; i < urls.Count; i++)
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,836 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,288 questions
0 comments No comments
{count} votes

Accepted answer
  1. P a u l 10,406 Reputation points
    2021-10-10T20:47:33.733+00:00

    The WebClient.DownloadFileAsync method only supports one active request per WebClient instance, so you'd have to either wait for the previous request to complete before initiating the next request, or you'd need to use one WebClient instance per request. DownloadFileAsync is non-blocking, so it'll schedule the request & notify consumers by firing the WebClient.DownloadFileCompleted event once it's finished.

    There's a similar version of this method WebClient.DownloadFileTaskAsync that returns a Task, so you could go through your loop calling this method, adding each Task to a collection, then calling Task.WhenAll after the loop, which you can use to wait for all your file downloads to complete.

    The question is if you have all file downloads occurring simultaneously, but you only have one progress bar, how should the progress be updated? If all file downloads update the same progress bar with their progress they'll all just be overwriting each other's progress.

    You could show multiple progress bars, although that's not the most scalable solution, so would you expect the progress bar to reflect the total progress across all requests?


0 additional answers

Sort by: Most helpful