Skip to content

Commit

Permalink
Add FixedDurationBar subclass of ProgressBar for the cases where you …
Browse files Browse the repository at this point in the history
…want to display a progress with a well known fixed duration
  • Loading branch information
Mpdreamz committed Aug 25, 2018
1 parent 88d8cf5 commit 17dcbaa
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 10 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ var childOptions = new ProgressBarOptions

![children_no_collapse](https://github.com/Mpdreamz/shellprogressbar/raw/master/doc/children-no-collapse-windows.gif)


# FixedDurationBar

`ProgressBar` is great for visualizing tasks with an unknown runtime. If you have a task that you know takes a fixed amount of time there is also a `FixedDurationBar` subclass.
`FixedDurationBar` will `Tick()` automatically but other then that all the options and usage are the same. Except it relies on the real time update feature so disabling that
will throw.

`FixedDurationBar` exposes an `IsCompleted` and `CompletedHandle`


### Credits

The initial implementation was inspired by this article.
Expand Down
39 changes: 39 additions & 0 deletions src/ShellProgressBar.Example/Examples/FixedDurationExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Threading;

namespace ShellProgressBar.Example.Examples
{
public class FixedDurationExample : ExampleBase
{
protected override void Start()
{
var options = new ProgressBarOptions
{
ForegroundColor = ConsoleColor.Yellow,
ForegroundColorDone = ConsoleColor.DarkGreen,
BackgroundColor = ConsoleColor.DarkGray,
BackgroundCharacter = '\u2593'
};
var wait = TimeSpan.FromSeconds(25);
using (var pbar = new FixedDurationBar(wait, "", options))
{
var t = new Thread(()=> LongRunningTask(pbar));
t.Start();

if (!pbar.CompletedHandle.WaitOne(wait))
Console.Error.WriteLine($"{nameof(FixedDurationBar)} did not signal {nameof(FixedDurationBar.CompletedHandle)} after {wait}");

}
}

private static void LongRunningTask(FixedDurationBar bar)
{
for (var i = 0; i < 1_000_000; i++)
{
bar.Message = $"{i} events";
if (bar.IsCompleted) break;
Thread.Sleep(1);
}
}
}
}
3 changes: 1 addition & 2 deletions src/ShellProgressBar.Example/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -14,6 +12,7 @@ class Program
{
private static readonly IList<IProgressBarExample> TestCases = new List<IProgressBarExample>
{
new FixedDurationExample(),
new DeeplyNestedProgressBarTreeExample(),
new NestedProgressBarPerStepProgress(),
new DrawsOnlyOnTickExample(),
Expand Down
37 changes: 37 additions & 0 deletions src/ShellProgressBar/FixedDurationBar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Threading;

namespace ShellProgressBar
{
public class FixedDurationBar : ProgressBar
{
public bool IsCompleted { get; private set; }

private readonly ManualResetEvent _completedHandle = new ManualResetEvent(false);
public WaitHandle CompletedHandle => _completedHandle;

public FixedDurationBar(TimeSpan duration, string message, ConsoleColor color) : this(duration, message, new ProgressBarOptions {ForegroundColor = color}) { }

public FixedDurationBar(TimeSpan duration, string message, ProgressBarOptions options = null) : base((int)Math.Ceiling(duration.TotalSeconds), message, options)
{
if (!this.Options.DisplayTimeInRealTime)
throw new ArgumentException(
$"{nameof(ProgressBarOptions)}.{nameof(ProgressBarOptions.DisplayTimeInRealTime)} has to be true for {nameof(FixedDurationBar)}", nameof(options)
);
}

private long _seenTicks = 0;
protected override void OnTimerTick()
{
Interlocked.Increment(ref _seenTicks);
if (_seenTicks % 2 == 0) this.Tick();
base.OnTimerTick();
}

protected override void OnDone()
{
this.IsCompleted = true;
this._completedHandle.Set();
}
}
}
7 changes: 6 additions & 1 deletion src/ShellProgressBar/ProgressBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ProgressBar(int maxTicks, string message, ProgressBarOptions options = nu
TaskbarProgress.SetState(TaskbarProgress.TaskbarStates.Normal);

if (this.Options.DisplayTimeInRealTime)
_timer = new Timer((s) => DisplayProgress(), null, 500, 500);
_timer = new Timer((s) => OnTimerTick(), null, 500, 500);
else //draw once
_timer = new Timer((s) =>
{
Expand All @@ -67,6 +67,11 @@ public ProgressBar(int maxTicks, string message, ProgressBarOptions options = nu
});
}

protected virtual void OnTimerTick()
{
DisplayProgress();
}

protected override void Grow(ProgressBarHeight direction)
{
switch (direction)
Expand Down
14 changes: 7 additions & 7 deletions src/ShellProgressBar/ShellProgressBar.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<PackageId>ShellProgressBar</PackageId>
<Title>Cross platform simple and complex progressbars on the command line!</Title>
<Authors>Martijn Laarman</Authors>
<PackageLicenseUrl>https://mpdreamz.mit-license.org/</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/Mpdreamz/shellprogressbar</PackageProjectUrl>
<PackageIconUrl>https://raw.github.com/Mpdreamz/shellprogressbar/master/src/nuget-icon.png</PackageIconUrl>
<PackageTags>console;shell;terminal;progress;progressbar</PackageTags>
<PackageId>ShellProgressBar</PackageId>
<Title>Cross platform simple and complex progressbars on the command line!</Title>
<Authors>Martijn Laarman</Authors>
<PackageLicenseUrl>https://mpdreamz.mit-license.org/</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/Mpdreamz/shellprogressbar</PackageProjectUrl>
<PackageIconUrl>https://raw.github.com/Mpdreamz/shellprogressbar/master/src/nuget-icon.png</PackageIconUrl>
<PackageTags>console;shell;terminal;progress;progressbar</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.0.1" />
Expand Down

0 comments on commit 17dcbaa

Please sign in to comment.