How can I make the percentages text above the progressBar1 to move at the same time/speed with the progressBar1 green color bar inside ?

Shalva Gabriel 61 Reputation points
2021-10-20T22:51:54.963+00:00
using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Diagnostics;  
using System.Drawing;  
using System.Drawing.Imaging;  
using System.IO;  
using System.Linq;  
using System.Net;  
using System.Net.Http;  
using System.Text;  
using System.Threading;  
using System.Threading.Tasks;  
using System.Windows.Forms;  
using unfreez_wrapper;  
  
namespace Downloads  
{  
    public partial class Form1 : Form  
    {  
        List<string> urls = new List<string>();  
        DownloadProgressTracker tracker;  
        long myLong = 0;  
  
        public Form1()  
        {  
            InitializeComponent();  
  
            tracker = new DownloadProgressTracker(50, TimeSpan.FromMilliseconds(500));  
  
            lblDownloadProgress.Text = "";  
            lblStatus.Text = "Download Pending";  
            lblAmount.Text = "";  
            lblSpeed.Text = "";  
            urls.Add("https://speed.hetzner.de/10GB.bin");  
            urls.Add("https://speed.hetzner.de/100MB.bin");  
        }  
  
        private async Task DownloadAsync()  
        {  
            using (var client = new WebClient())  
            {  
                client.DownloadFileCompleted += (s, e) => lblStatus.Text = "Download File Completed.";  
                client.DownloadProgressChanged += (s, e) => tracker.SetProgress(e.BytesReceived, e.TotalBytesToReceive);  
                client.DownloadProgressChanged += (s, e) => lblAmount.Text = tracker.SizeSuffix(e.BytesReceived) + "/" + tracker.SizeSuffix(e.TotalBytesToReceive);  
                client.DownloadProgressChanged += (s, e) => lblSpeed.Text = tracker.GetBytesPerSecondString();  
                client.DownloadProgressChanged += (s, e) => myLong = Convert.ToInt64(client.ResponseHeaders["Content-Length"]);  
                client.DownloadProgressChanged += (s, e) =>  
                {  
                    progressBar1.Value = e.ProgressPercentage;  
                    lblDownloadProgress.Text = e.ProgressPercentage.ToString() + "%";  
                    lblDownloadProgress.Left = Math.Min(  
                        (int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width),  
                        progressBar1.Width - lblDownloadProgress.Width  
                    );  
                };  
  
                for (int i = 0; i < urls.Count; i++)  
                {  
                    tracker.NewFile();  
  
                    await client.DownloadFileTaskAsync(new Uri(urls[i]), @"d:\satImages\img" + i + ".gif");  
                }  
            }  
        }  
  
        private void Form1_Load(object sender, EventArgs e)  
        {  
  
        }  
  
        private async void btnStart_Click(object sender, EventArgs e)  
        {  
            lblStatus.Text = "Downloading...";  
            await DownloadAsync();  
        }  
  
        private void btnStop_Click(object sender, EventArgs e)  
        {  
            lblStatus.Text = "Download Stopped";  
        }  
    }  
}  

The percentages text "%" is moving each time by one before the green bar in the progressbar is moving. First the percentage move then the bar.
First the percentages in the screenshot is changing 1% then after 200-300 milliseconds or so the green bar of the progressBar1 is changing to 1.

They are not changing at the same time.

142225-111.jpg

The class DownloadProgressTracker

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
  
namespace Downloads  
{  
    class DownloadProgressTracker  
    {  
        private long _totalFileSize;  
        private readonly int _sampleSize;  
        private readonly TimeSpan _valueDelay;  
  
        private DateTime _lastUpdateCalculated;  
        private long _previousProgress;  
  
        private double _cachedSpeed;  
  
        private Queue<Tuple<DateTime, long>> _changes = new Queue<Tuple<DateTime, long>>();  
  
        public DownloadProgressTracker(int sampleSize, TimeSpan valueDelay)  
        {  
            _lastUpdateCalculated = DateTime.Now;  
            _sampleSize = sampleSize;  
            _valueDelay = valueDelay;  
        }  
  
        public void NewFile()  
        {  
            _previousProgress = 0;  
        }  
  
        public void SetProgress(long bytesReceived, long totalBytesToReceive)  
        {  
            _totalFileSize = totalBytesToReceive;  
  
            long diff = bytesReceived - _previousProgress;  
            if (diff <= 0)  
                return;  
  
            _previousProgress = bytesReceived;  
  
            _changes.Enqueue(new Tuple<DateTime, long>(DateTime.Now, diff));  
            while (_changes.Count > _sampleSize)  
                _changes.Dequeue();  
        }  
  
        public double GetProgress()  
        {  
            return _previousProgress / (double)_totalFileSize;  
        }  
  
        public string GetProgressString()  
        {  
            return String.Format("{0:P0}", GetProgress());  
        }  
  
        public string GetBytesPerSecondString()  
        {  
            double speed = GetBytesPerSecond();  
            var prefix = new[] { "", "K", "M", "G" };  
  
            int index = 0;  
            while (speed > 1024 && index < prefix.Length - 1)  
            {  
                speed /= 1024;  
                index++;  
            }  
  
            int intLen = ((int)speed).ToString().Length;  
            int decimals = 3 - intLen;  
            if (decimals < 0)  
                decimals = 0;  
  
            string format = String.Format("{{0:F{0}}}", decimals) + "{1}B/s";  
  
            return String.Format(format, speed, prefix[index]);  
        }  
  
        public double GetBytesPerSecond()  
        {  
            if (DateTime.Now >= _lastUpdateCalculated + _valueDelay)  
            {  
                _lastUpdateCalculated = DateTime.Now;  
                _cachedSpeed = GetRateInternal();  
            }  
  
            return _cachedSpeed;  
        }  
  
        private double GetRateInternal()  
        {  
            if (_changes.Count == 0)  
                return 0;  
  
            TimeSpan timespan = _changes.Last().Item1 - _changes.First().Item1;  
            long bytes = _changes.Sum(t => t.Item2);  
  
            double rate = bytes / timespan.TotalSeconds;  
  
            if (double.IsInfinity(rate) || double.IsNaN(rate))  
                return 0;  
  
            return rate;  
        }  
  
        static readonly string[] SizeSuffixes =  
                   { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };  
        public string SizeSuffix(Int64 value, int decimalPlaces = 1)  
        {  
            if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }  
            if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); }  
            if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }  
  
            // mag is 0 for bytes, 1 for KB, 2, for MB, etc.  
            int mag = (int)Math.Log(value, 1024);  
  
            // 1L << (mag * 10) == 2 ^ (10 * mag)   
            // [i.e. the number of bytes in the unit corresponding to mag]  
            decimal adjustedSize = (decimal)value / (1L << (mag * 10));  
  
            // make adjustment when the value is large enough that  
            // it would round up to 1000 or more  
            if (Math.Round(adjustedSize, decimalPlaces) >= 1000)  
            {  
                mag += 1;  
                adjustedSize /= 1024;  
            }  
  
            return string.Format("{0:n" + decimalPlaces + "} {1}",  
                adjustedSize,  
                SizeSuffixes[mag]);  
        }  
    }  
}  
  
Developer technologies | Windows Forms
Developer technologies | C#
{count} votes

Accepted answer
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2021-10-21T11:31:40.287+00:00

    Perhaps having the percent show in the ProgressBar would be a better option.

    This screenshot is Progress-o-Doom in one of my applications
    142501-doom.png

    Which is a custom ProgressBar, Progress-O-Doom

    142467-doom1.png

    0 comments No comments

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.