-
-
Save granddalf/93aff56ba94cb8bb606576b5a136ad87 to your computer and use it in GitHub Desktop.
ProgressBar in Console C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Text; | |
using System.Threading; | |
/// <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 string currentText = string.Empty; | |
private bool disposed = false; | |
private int animationIndex = 0; | |
public ProgressBar() { | |
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval); | |
} | |
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; | |
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); | |
} | |
} | |
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; | |
} | |
public void Dispose() { | |
lock (timer) { | |
disposed = true; | |
UpdateText(string.Empty); | |
timer.Dispose(); | |
} | |
} | |
} | |
//USAGE | |
static class Program { | |
static void Main() { | |
Console.Write("Performing some task... "); | |
using (var progress = new ProgressBar()) { | |
for (int i = 0; i <= 100; i++) { | |
progress.Report((double) i / 100); | |
Thread.Sleep(20); | |
} | |
} | |
Console.WriteLine("Done."); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment