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);
}
}
}
}
----------------------------------------------
{
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();
---------------------------------------------------


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())Console.WriteLine( "Testing Ongoing... ");
{
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
Post a Comment