How to download multiple files in C# using Parallel

By FoxLearn 7/19/2024 2:41:00 AM   8.24K
Downloading multiple files in parallel in a C# Windows Forms Application can be efficiently achieved using asynchronous programming techniques along with Task and HttpClient.

Creating a new Windows Forms application project, then drag and drop the ProgressBar, RichTextBox, Label and Button controls from the Visual Studio toolbox to your winform. You can design a simple UI that allows you to download multiple files through multiple threads as shown below.

parallel download multiple files in c#

Create a Website class to map data return from the site that you want to download data.

public class Website
{
    public string Url { get; set; }
    public string Data { get; set; }
}

Create a ProgressReport class to update your percentage download to the progress bar control.

public class ProgressReport
{
    public int PercentageComplete { get; set; }
    public List<Website> SitesDownloaded { get; set; }
}

Create a SiteDownload class to help you download the list of website that you initialize.

To download multiple files in C# using Parallel, you can utilize Parallel.ForEach to distribute the download tasks across multiple threads.

public class SiteDownload
{
    public static List<string> Sites()
    {
        // List of file URLs to download
        List<string> list = new List<string>();
        list.Add("http://foxlearn.com");
        list.Add("http://c-sharpcode.com");
        list.Add("http://ebook-dl.net");
        return list;
    }

    public static async Task<List<Website>> ParallelDownload(IProgress<ProgressReport> progress, CancellationTokenSource cancellationTokenSource)
    {
        List<string> sites = Sites();
        List<Website> list = new List<Website>();
        ProgressReport progressReport = new ProgressReport();
        ParallelOptions parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = 8;
        parallelOptions.CancellationToken = cancellationTokenSource.Token;
        await Task.Run(() =>
        {
            try
            {
                Parallel.ForEach<string>(sites, parallelOptions, (site) =>
                {
                    Website results = Download(site);
                    list.Add(results);
                    progressReport.SitesDownloaded = list;
                    progressReport.PercentageComplete = (list.Count * 100) / sites.Count;
                    progress.Report(progressReport);
                    parallelOptions.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (OperationCanceledException ex)
            {
                throw ex;
            }
        });

        return list;
    }

    private static Website Download(string url)
    {
        Website website = new Website();
        WebClient client = new WebClient();
        website.Url = url;
        website.Data = client.DownloadString(url);
        return website;
    }
}

You can get the list of site data that you want to download. Using async parallel c# helps your program run faster, it will create multiple threads based on the number of CPU cores.

We will write c# code run multiple tasks in parallel, you can do the same way with download multiple images from url c# or download file from url to folder.

A faster way to download multiple files or images based on url is to use parallel to create multiple threads, which increases high performance file download that constraining concurrent threads in c#.

Next, Add code to handle your winform as shown below.

Create the PrintResults method allows you to display the download file information into the RichTextBox control.

void PrintResults(List<Website> results)
{
    richTextBox1.Text = string.Empty;
    foreach (var item in results)
        richTextBox1.Text += $"{ item.Url } downloaded: { item.Data.Length } characters long.{ Environment.NewLine }";
}

Create the ReportProgress method allows you to upload the progress bar and label controls, then call the PrintResults method to display the dowload file information.

void ReportProgress(object sender, ProgressReport e)
{
    progressBar1.Value = e.PercentageComplete;
    lblPercent.Text = $"Completed: {e.PercentageComplete} %";
    PrintResults(e.SitesDownloaded);
}

Add the click event handler to the Download button that lets you handle the download file.

CancellationTokenSource cancellationTokenSource;

private async void btnDownload_Click(object sender, EventArgs e)
{
    try
    {
        cancellationTokenSource = new CancellationTokenSource();
        Progress<ProgressReport> progress = new Progress<ProgressReport>();
        progress.ProgressChanged += ReportProgress;
        var watch = Stopwatch.StartNew();
        var results = await SiteDownload.ParallelDownload(progress, cancellationTokenSource);
        PrintResults(results);
        watch.Stop();
        var elapsed = watch.ElapsedMilliseconds;
        richTextBox1.Text += $"Total execution time: { elapsed }";
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        cancellationTokenSource.Dispose();
    }
}

And don't forget to add the click event handler to the Stop button allows you to cancel download file.

private void btnStop_Click(object sender, EventArgs e)
{
    if (cancellationTokenSource != null)
        cancellationTokenSource.Cancel();
}

The Stopwatch class has methods and properties that you can use to accurately measure elapsed time.

A Stopwatch instance can measure the time that has elapsed over a period of time or the total amount of time that has elapsed in many time periods.