c# console applicaton progress bar with spinner

Name spaces to include:

using System;
using System.Text;
using System.Threading;
----------------------------------------------
Progress bar class:

    class progressBar
    {
        /// <summary>
        /// An ASCII progress bar
        /// </summary>
        public class ProgressBar : IDisposable, IProgress<double>
        {
            private const int blockCount = 40;
            private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
           private const string animation = @"▀▀▀▀▄▄▄▄";//@"▀▀▀▀▄▄▄▄"  @"|/-\";

            private readonly Timer timer;

            private double currentProgress = 0;
            private string currentText = string.Empty;
            private bool disposed = false;
            private int animationIndex = 0;

            public ProgressBar()
            {
                timer = new Timer(TimerHandler);

                // A progress bar is only for temporary display in a console window.
                // If the console output is redirected to a file, draw nothing.
                // Otherwise, we'll end up with a lot of garbage in the target file.
                if (!Console.IsOutputRedirected)
                {
                    ResetTimer();
                }
            }

            public void Report(double value)
            {
                // Make sure value is in [0..1] range
                value = Math.Max(0, Math.Min(1, value));
                Interlocked.Exchange(ref currentProgress, value);
            }

            private void TimerHandler(object state)
            {
                lock (timer)
                {
                    if (disposed) return;
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    int progressBlockCount = (int)(currentProgress * blockCount);
                    int percent = (int)(currentProgress * 100);
                    string text = string.Format("{0}{1} {2,3}% {3}",
                        new string('█', progressBlockCount), new string('▒', blockCount - progressBlockCount),//░ ▒ █ ▓
                        percent,
                        animation[animationIndex++ % animation.Length]);
                    UpdateText(text);
                    Console.ResetColor();
                    ResetTimer();
                }
            }

            private void UpdateText(string text)
            {
                // Get length of common portion
                int commonPrefixLength = 0;
                int commonLength = Math.Min(currentText.Length, text.Length);
                while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
                {
                    commonPrefixLength++;
                }

                // Backtrack to the first differing character
                StringBuilder outputBuilder = new StringBuilder();
                outputBuilder.Append('\b', currentText.Length - commonPrefixLength);

                // Output new suffix
                outputBuilder.Append(text.Substring(commonPrefixLength));

                // If the new text is shorter than the old one: delete overlapping characters
                int overlapCount = currentText.Length - text.Length;
                if (overlapCount > 0)
                {
                    outputBuilder.Append(' ', overlapCount);
                    outputBuilder.Append('\b', overlapCount);
                }

                Console.Write(outputBuilder);
                currentText = text;
            }

            private void ResetTimer()
            {
                timer.Change(animationInterval, TimeSpan.FromMilliseconds(-1));
            }

            public void Dispose()
            {
                lock (timer)
                {
                    disposed = true;
                    UpdateText(string.Empty);
                }
            }

        }
    }
----------------------------------------------
Implementation:
       
   Console.WriteLine( "Testing Ongoing... ");
            using (var progress = new progressBar.ProgressBar())
            {
                float totRows = 100;
                float inCent = 100 / totRows;
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    progress.Report((double)((i + 1) * inCent) / 100);
                }
            }

            Console.WriteLine("testing complete");

----------------------------------------------------
       MODIFIED [Two level progress]
-----------------------------------------------------

Progress bar class:

class MyProgressBar
    {
        // <summary>
        /// An ASCII progress bar
        /// </summary>
        public class ProgressBar : IDisposable, IProgress<double>
        {
            private const int blockCount = 10;
            private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
            private const string animation = @"▀▀▀▀▄▄▄▄";//@"▀▀▀▀▄▄▄▄"  @"|/-\";

            private readonly Timer timer;

            private double currentProgress = 0;
            private double jcurrentProgress = 0;

            private string dispText = "";

            private string currentText = string.Empty;
            private bool disposed = false;
            private int animationIndex = 0;

            private int barLevel = 1;

            public ProgressBar()
            {
                timer = new Timer(TimerHandler);

                // A progress bar is only for temporary display in a console window.
                // If the console output is redirected to a file, draw nothing.
                // Otherwise, we'll end up with a lot of garbage in the target file.
                if (!Console.IsOutputRedirected)
                {
                    ResetTimer();
                }
            }

            public void Report(double value, double jValue, string text = "")
            {
                // Make sure value is in [0..1] range
                value = Math.Max(0, Math.Min(1, value));
                jValue = Math.Max(0, Math.Min(1, jValue));

                Interlocked.Exchange(ref currentProgress, value);
                Interlocked.Exchange(ref jcurrentProgress, jValue);

                Interlocked.Exchange(ref dispText, text);

                barLevel = 2;
            }

            private void TimerHandler(object state)
            {
                lock (timer)
                {
                    if (disposed) return;
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    string text = "";
                    if (barLevel == 1)
                    {
                        int progressBlockCount = (int)(currentProgress * blockCount);
                        int percent = (int)(currentProgress * 100);
                        text = string.Format("{3} {0}{1} {2,3}% {4}",
                            new string('█', progressBlockCount), new string('▒', blockCount - progressBlockCount),//░ ▒ █ ▓ ▀▄
                            percent,
                            animation[animationIndex++ % animation.Length],
                            ">> " + dispText
                            );
                    }
                    else if (barLevel == 2)
                    {
                        int progressBlockCount = (int)(currentProgress * blockCount);
                        int jprogressBlockCount = (int)(jcurrentProgress * blockCount);

                        int percent = (int)(currentProgress * 100);
                        int jpercent = (int)(jcurrentProgress * 100);

                        text = string.Format("{3} {0}{1}{2,3}% || {4}{5}{6,3}% {7}",
                            new string('█', progressBlockCount),
                            new string('▒', blockCount - progressBlockCount),
                            percent,
                            animation[animationIndex++ % animation.Length],
                            new string('█', jprogressBlockCount),
                            new string('▒', blockCount - jprogressBlockCount),
                            jpercent,
                            ">> " + dispText
                            );
                    }

                    UpdateText(text);

                    Console.ResetColor();
                    ResetTimer();
                }
            }

            private void UpdateText(string text)
            {
                // Get length of common portion
                int commonPrefixLength = 0;
                int commonLength = Math.Min(currentText.Length, text.Length);
                while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
                {
                    commonPrefixLength++;
                }

                // Backtrack to the first differing character
                StringBuilder outputBuilder = new StringBuilder();
                outputBuilder.Append('\b', currentText.Length - commonPrefixLength);

                // Output new suffix
                outputBuilder.Append(text.Substring(commonPrefixLength));

                // If the new text is shorter than the old one: delete overlapping characters
                int overlapCount = currentText.Length - text.Length;
                if (overlapCount > 0)
                {
                    outputBuilder.Append(' ', overlapCount);
                    outputBuilder.Append('\b', overlapCount);
                }

                Console.Write(outputBuilder);
                currentText = text;
            }

            private void ResetTimer()
            {
                timer.Change(animationInterval, TimeSpan.FromMilliseconds(-1));
            }

            public void Dispose()
            {
                lock (timer)
                {
                    disposed = true;
                    UpdateText(string.Empty);
                }
            }

            public void Report(double value, string text)
            {
                // Make sure value is in [0..1] range
                value = Math.Max(0, Math.Min(1, value));
                Interlocked.Exchange(ref currentProgress, value);

                Interlocked.Exchange(ref dispText, text);
            }

            public void Report(double value)
            {
                // Make sure value is in [0..1] range
                value = Math.Max(0, Math.Min(1, value));
                Interlocked.Exchange(ref currentProgress, value);
            }
        }
    }
----------------------------------------------------
Implementation:

 Console.WriteLine("Testing Ongoing... ");
            using (var progress = new MyProgressBar.ProgressBar())
            {
// EXAMPLE 1 (TWO PROGRESS BARS)
                float totRows = 10;
                float inCent = 100 / totRows;
                for (int i = 0; i < totRows; i++)
                {
                    float jtotRows = 5;
                    float jinCent = 100 / jtotRows;

                    for (int j = 0; j < jtotRows; j++)
                    {
                        System.Threading.Thread.Sleep(1000);
                        progress.Report((double)((i) * inCent) / 100, (double)((j + 1) * jinCent) / 100, "Processing: " + j);
                    }

                }
            }

// EXAMPLE  2 (ONE PROGRESS BAR)
            using (var progress = new MyProgressBar.ProgressBar())
            {
                float totRows = 50;
                float inCent = 100 / totRows;
                for (int i = 0; i < totRows; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    progress.Report((double)((i + 1) * inCent) / 100, "Processing: " + i);
                }
            }

            Console.WriteLine("testing complete");

            Console.Read();

---------------------------------------------------





Comments

Popular posts from this blog

Paging, sorting and searching in mvc + razor

C# SELF DESTRUCT CONSOLE APP