budul.ProgressWatcher
2.1.0
dotnet add package budul.ProgressWatcher --version 2.1.0
NuGet\Install-Package budul.ProgressWatcher -Version 2.1.0
<PackageReference Include="budul.ProgressWatcher" Version="2.1.0" />
<PackageVersion Include="budul.ProgressWatcher" Version="2.1.0" />
<PackageReference Include="budul.ProgressWatcher" />
paket add budul.ProgressWatcher --version 2.1.0
#r "nuget: budul.ProgressWatcher, 2.1.0"
#:package budul.ProgressWatcher@2.1.0
#addin nuget:?package=budul.ProgressWatcher&version=2.1.0
#tool nuget:?package=budul.ProgressWatcher&version=2.1.0
ProgressWatcher
Lightweight, thread-safe progress coordination library for nested and parallel operations.
- PackageId:
budul.ProgressWatcher - Supported TFMs:
netstandard2.0,netstandard2.1,net7.0,net8.0 - Repository: https://github.com/budul100/ProgressWatcher
- License: MIT
Overview
ProgressWatcher provides a small API to create progress packages (IPackage) and a top-level Watcher that aggregates progress and status information for UI or logging consumers. Packages support nested child packages, fractional progress reporters (IProgress<double>), and efficient thread-local batching for high-concurrency scenarios.
Installation
Install from NuGet:
dotnet add package budul.ProgressWatcher
Quick start (synchronous)
using ProgressWatcher;
var watcher = new Watcher();
var package = watcher.GetPackage(allSteps: 3, status: "Starting work...");
package.NextStep("Step 1 done");
package.NextStep("Step 2 done");
package.NextStep("Step 3 done");
package.Dispose(); // or package.Complete()
// watcher.ProgressAll, watcher.ProgressTip and watcher.Status update via PropertyChanged
Parallel usage (hot loops)
For high-concurrency loops (e.g. Parallel.ForEach or many threads) use NextStepLocal() to avoid contention. After the loop finishes, call FlushCounterLocal() to ensure any thread-local counts are aggregated and reported.
using ProgressWatcher;
using System.Threading.Tasks;
var items = Enumerable.Range(0, 1_000_000);
var watcher = new Watcher();
var package = watcher.GetPackage(items, "Processing items");
Parallel.ForEach(items, item => { // work on item...
// report work from current thread using thread-local batching
package.NextStepLocal();
});
// ensure remaining local counts are flushed
package.FlushCounterLocal();
package.Dispose();
Important notes:
- Always call
FlushCounterLocal()after a parallel loop; otherwise some thread-local counts may remain unreported. NextStepLocal()is intended for hot/tight loops and batches updates on a per-thread basis to reduce synchronization costs.
Using progress reporters and weights
Get a fractional progress reporter when you need to report continuous progress from a subtask:
var parent = watcher.GetPackage(status: "Parent", steps: 1);
using var reporter = parent.GetProgress(status: "Loading", steps: 10, weight: 0.5)
{
reporter.NextStep(4);
}
parent.Dispose();
Weights:
weightis a value in [0.0, 1.0] that assigns how much of the parent's remaining progress the child consumes.- Passing
0uses automatic weight calculation based on remaining steps.
Nesting and lifecycle
- Create nested work with
GetPackage(...)or fractional reporters withGetProgress(...). - Call
Dispose()on a package to complete it and notify the parent.Complete()sets progress to 100% immediately. - Top-level
Watcherexposes events:ProgressStarted,ProgressCompleted,ChildStarted,ChildDisposedand propertiesProgressAll,ProgressTip,Status,IsRunning(useful for UI binding).
Thread-safety and throttling
Packageis designed for concurrent reporting. UseNextStepLocal()in parallel scenarios andFlushCounterLocal()afterwards.- Progress updates are internally throttled using a minimum delta and minimum interval before forwarding to the parent. This avoids flooding UI updates while remaining responsive.
Best practices
- Prefer
NextStepLocal()inside parallel loops; callFlushCounterLocal()after the loop. - Dispose or
Complete()packages to ensure parents advance to completion. - Use
GetProgress(...)for long-running subtasks that report fractional progress.
API summary
Watcher� top-level aggregator; useGetPackage(...)to start work and bind toProgressAll,ProgressTip,Status.IPackage� useNextStep(),NextStepLocal(),GetPackage(...),GetProgress(...),FlushCounterLocal(),Complete(),Dispose().
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
.NETStandard 2.1
- No dependencies.
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.