When downloading multiple files and updating a progressBar , how to animate the progressBar back from 100% to 0 ?

Daniel Lee 61 Reputation points
2023-12-11T04:38:21.8766667+00:00

When started downloading the files the first file progrssBar1 is getting to 100% when the file finish downloading and then it's animating the green bar inside the progressBar1 making it smooth moving from 100% to 0%, this is the logic I want to do.

the problem is when the progressBar start progress back from 100% to 0% the green color is blinking then when it's getting to 0% and the next file is start downloading the progressBar1 green color the progress itself start getting "crazy" and it's moving forward then backward forward all the time changing directions fast.

the logic is that each downloading file I want the progressBar1 to get from 0 to 100% showing the download progress then smooth changing in animation from 100% to 0 and then start downloading the next file.

I can't figure how why it's acting in that behavior? and how to fix it?

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Downloads
{
    public partial class Form1 : Form
    {
        private string destinationFolderPath;

        // Event to signal when a download is completed
        public event EventHandler<DownloadEventArgs> DownloadCompleted;

        public Form1()
        {
            InitializeComponent();

            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;
            progressBar2.Minimum = 0;
            progressBar2.Maximum = 100;

            // Subscribe to the event
            DownloadCompleted += OnDownloadCompleted;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            var downloadFileUrl = "https://onlinetestcase.com/wp-content/uploads/2023/06/25-MB.wmv";
            destinationFolderPath = Path.GetFullPath(@"d:\");

            int numberOfDownloads = 200;

            for (int i = 1; i <= numberOfDownloads; i++)
            {
                string destinationFilePath = Path.Combine(destinationFolderPath, $"file_{i}.wmv");

                using (HttpClient client = new HttpClient())
                {
                    string url = downloadFileUrl;

                    // Move the declaration inside the loop
                    int downloadNumber = i;

                    var progress = new Progress<DownloadProgress>(dp => ReportProgress(dp.Percent, downloadNumber, dp.ExpectedSize));

                    // Offload the download operation to a separate thread
                    await Task.Run(() => DownloadFileAsync(client, url, destinationFilePath, progress, downloadNumber));
                }
            }
        }

        async Task DownloadFileAsync(HttpClient client, string url, string destination, IProgress<DownloadProgress> progress, int downloadNumber)
        {
            using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
            {
                response.EnsureSuccessStatusCode();

                using (var stream = await response.Content.ReadAsStreamAsync())
                using (var fileStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
                {
                    var buffer = new byte[8192];
                    long totalRead = 0;
                    int bytesRead;

                    while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        await fileStream.WriteAsync(buffer, 0, bytesRead);
                        totalRead += bytesRead;

                        // Report progress
                        var downloadProgress = new DownloadProgress
                        {
                            Percent = (int)((double)totalRead / response.Content.Headers.ContentLength.Value * 100),
                            DownloadNumber = downloadNumber,
                            ExpectedSize = response.Content.Headers.ContentLength.Value
                        };

                        progress.Report(downloadProgress);
                    }
                }

                // Raise the DownloadCompleted event when the download is successful
                DownloadCompleted?.Invoke(this, new DownloadEventArgs(downloadNumber, destination));
            }
        }

        void ReportProgress(int percent, int downloadNumber, long expectedSize)
        {
            // Update the progress bar for the specific download
            progressBar1.Value = percent;

            // Check if the download has completed
            if (percent == 100)
            {
                string destinationFilePath = Path.Combine(destinationFolderPath, $"file_{downloadNumber}.wmv");

                // Check if the file exists
                if (File.Exists(destinationFilePath))
                {
                    // Optionally, check the file size against the expected size
                    long actualSize = new FileInfo(destinationFilePath).Length;

                    if (actualSize == expectedSize)
                    {
                        string status = $"Download {downloadNumber}: Completed successfully";
                        // Update a label or print to console, etc.
                        label1.Text = status;
                    }
                    else
                    {
                        string status = $"Download {downloadNumber}: Completed with size mismatch";
                        // Handle size mismatch (optional)
                        label1.Text = status;
                    }
                }
                else
                {
                    string status = $"Download {downloadNumber}: File does not exist";
                    // Handle file not found (optional)
                    label1.Text = status;
                }
            }
            else
            {
                // Display the amount downloaded and download speed
                double bytesDownloaded = progressBar1.Maximum * percent / 100.0;
                double downloadSpeed = bytesDownloaded / progressBar1.Value * 1000; // Speed in bytes per second

                string status = $"Download {downloadNumber}: {FormatBytes(bytesDownloaded)} - Speed: {FormatBytes(downloadSpeed)}/s";

                // Update a label or print to console, etc.
                label1.Text = status;
            }
        }

        private void OnDownloadCompleted(object sender, DownloadEventArgs e)
        {
            // Set the progress bar to 100
            UpdateProgressBar(100);

            // Simulate a delay or animate the progress bar reaching 100
            Task.Run(async () =>
            {
                for (int i = 100; i >= 0; i--)
                {
                    // Update the progress bar on the UI thread
                    UpdateProgressBar(i);

                    await Task.Delay(20); // Adjust the delay time as needed
                }
            });
        }

        private void UpdateProgressBar(int value)
        {
            if (progressBar1.InvokeRequired)
            {
                // Use Invoke to marshal the call to the UI thread
                Invoke(new Action<int>(UpdateProgressBar), value);
            }
            else
            {
                // Update the progress bar value
                progressBar1.Value = value;
                // Force the UI to update
                progressBar1.Refresh(); // or progressBar1.Invalidate();
            }
        }

        private string FormatBytes(double bytes)
        {
            string[] suffixes = { "B", "KB", "MB", "GB", "TB" };
            int suffixIndex = 0;

            while (bytes >= 1024 && suffixIndex < suffixes.Length - 1)
            {
                bytes /= 1024;
                suffixIndex++;
            }

            return $"{bytes:N2} {suffixes[suffixIndex]}";
        }

        private class DownloadProgress
        {
            public int Percent { get; set; }
            public int DownloadNumber { get; set; }
            public long ExpectedSize { get; set; }
        }

        // Custom event arguments for download completion
        public class DownloadEventArgs : EventArgs
        {
            public int DownloadNumber { get; }
            public string DestinationFilePath { get; }

            public DownloadEventArgs(int downloadNumber, string destinationFilePath)
            {
                DownloadNumber = downloadNumber;
                DestinationFilePath = destinationFilePath;
            }
        }
    }
}
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,919 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.
11,230 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jiale Xue - MSFT 48,856 Reputation points Microsoft Vendor
    2023-12-11T07:36:19.8966667+00:00

    Hi @Daniel Lee , Welcome to Microsoft Q&A,

    Note Task.Delay(1) in the code below.

    You cannot delay for too long, as this will cause progress errors.

    You can try it.

     Task.Run(async () =>
     {
         for (int i = 100; i >= 0; i--)
         {
             // Update the progress bar on the UI thread
             UpdateProgressBar(i);
    
             await Task.Delay(1); // Adjust the delay time as needed
         }
     });
    

    Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.