-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6ab2ec7
commit 63f0078
Showing
5 changed files
with
172 additions
and
12 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
using System; | ||
using System.Text; | ||
using System.Threading; | ||
|
||
namespace THttpWebRequest.Utility | ||
{ | ||
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); | ||
|
||
// 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; | ||
|
||
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); | ||
|
||
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); | ||
} | ||
} | ||
|
||
} | ||
} |