IVSoftware.Portable.WatchdogTimer
1.1.2
There is a newer prerelease version of this package available.
See the version list below for details.
See the version list below for details.
The owner has unlisted this package.
This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package IVSoftware.Portable.WatchdogTimer --version 1.1.2
NuGet\Install-Package IVSoftware.Portable.WatchdogTimer -Version 1.1.2
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="IVSoftware.Portable.WatchdogTimer" Version="1.1.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="IVSoftware.Portable.WatchdogTimer" Version="1.1.2" />
<PackageReference Include="IVSoftware.Portable.WatchdogTimer" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add IVSoftware.Portable.WatchdogTimer --version 1.1.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: IVSoftware.Portable.WatchdogTimer, 1.1.2"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package IVSoftware.Portable.WatchdogTimer@1.1.2
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=IVSoftware.Portable.WatchdogTimer&version=1.1.2
#tool nuget:?package=IVSoftware.Portable.WatchdogTimer&version=1.1.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Watchdog timer
A timer designed to complete after the time span set by the Interval property has elapsed since the most recent call to the StartOrRestart method. This results in a single completion regardless of the number of restarts. Invoking the Cancel method negates any enqueued action or event in the queue.
Methods
/// <summary>
/// Restart the watchdog timer.
/// </summary>
/// <remarks>
/// Core method that can take a parameterized action as well as a custom EventArgs object.
/// </remarks>
public void StartOrRestart(Action action, EventArgs e)
{
Running = true;
_wdtCount++;
var capturedCount = _wdtCount;
_isCancelled= false;
Task
.Delay(Interval)
.GetAwaiter()
.OnCompleted(() =>
{
// If the 'captured' localCount has not changed after awaiting the Interval,
// it indicates that no new 'bones' have been thrown during that interval.
if (capturedCount.Equals(_wdtCount) && !_isCancelled)
{
action?.Invoke();
Running = false;
RanToCompletion?.Invoke(this, e ?? EventArgs.Empty);
}
});
}
/// <summary>
/// Restart the watchdog timer.
/// </summary>
/// <remarks>
/// Subscribe to the RanToCompletion event to receive notification of completion.
/// On completion, fire an event with an empty EventArgs object.
/// </remarks>
public void StartOrRestart() => StartOrRestart(null, EventArgs.Empty);
/// <summary>
/// Restart the watchdog timer.
/// </summary>
/// <remarks>
/// Subscribe to the RanToCompletion event to receive notification of completion.
/// On completion, fire an event using a custom parameterized EventArgs object.
/// </remarks>
public void StartOrRestart(EventArgs e) => StartOrRestart(null, e);
/// <summary>
/// Restart the watchdog timer.
/// </summary>
/// <remarks>
/// Subscribe to the RanToCompletion event to receive notification of completion.
/// On completion, invoke a parameterized action.
/// </remarks>
public void StartOrRestart(Action action) => StartOrRestart(action, EventArgs.Empty);
public void Cancel() => _isCancelled = true;
Properties
public TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(1);
public bool Running { get; private set; }
Event
public event EventHandler RanToCompletion;
Usage
Source and demo code is available on the GitHub.
using IVSoftware.Portable;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace testbench
{
internal class Program
{
static void Main(string[] args)
{
runAsync();
Console.ReadKey();
}
private static async void runAsync()
{
BringConsoleToFront();
// Three second watchdog timer
WatchdogTimer _wdt = new WatchdogTimer { Interval = TimeSpan.FromSeconds(3) };
// System.Diagnostics.Stopwatch for testing purposes.
Stopwatch _stopWatch = new Stopwatch();
#region T E S T A C T I O N
Console.WriteLine("T E S T A C T I O N");
_stopWatch.Start();
Console.WriteLine($"{_stopWatch.Elapsed} START");
_wdt.StartOrRestart(()=> MarkEmailAsRead(id: 1));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 2));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 3));
// Should run to completion
await Task.Delay(TimeSpan.FromSeconds(4));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 10));
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 20));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 30));
// Should run to completion
await Task.Delay(TimeSpan.FromSeconds(4));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
#endregion T E S T A C T I O N
#region T E S T C A N C E L
Console.WriteLine("T E S T C A N C E L");
_stopWatch.Restart();
Console.WriteLine($"{_stopWatch.Elapsed} START");
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 1), new CustomEventArgs(id: 1));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 2), new CustomEventArgs(id: 2));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 3), new CustomEventArgs(id: 3));
// Cancel event and allow enough time to otherwise complete.
await Task.Delay(TimeSpan.FromSeconds(2));
_wdt.Cancel();
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 10), new CustomEventArgs(id: 10));
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 20), new CustomEventArgs(id: 20));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(() => MarkEmailAsRead(id: 30), new CustomEventArgs(id: 30));
// Cancel event and allow enough time to otherwise complete.
await Task.Delay(TimeSpan.FromSeconds(2));
_wdt.Cancel();
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
#endregion T E S T C A N C E L
#region T E S T E V E N T
_wdt.RanToCompletion += onWdtRanToCompletion;
Console.WriteLine("T E S T E V E N T");
_stopWatch.Restart();
Console.WriteLine($"{_stopWatch.Elapsed} START");
_wdt.StartOrRestart(new CustomEventArgs(id: 1));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(new CustomEventArgs(id: 2));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(new CustomEventArgs(id: 3));
// Should run to completion
await Task.Delay(TimeSpan.FromSeconds(4));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(new CustomEventArgs(id: 10));
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(new CustomEventArgs(id: 20));
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(_stopWatch.Elapsed);
_wdt.StartOrRestart(new CustomEventArgs(id: 30));
// Should run to completion
await Task.Delay(TimeSpan.FromSeconds(4));
Console.WriteLine(_stopWatch.Elapsed + Environment.NewLine);
Console.WriteLine($"DONE {_stopWatch.Elapsed}");
#endregion T E S T E V E N T
#region L o c a l F x
void MarkEmailAsRead(int id)
{
Console.WriteLine($"Expired: {_stopWatch.Elapsed}");
Console.WriteLine($"The email with the ID '{id}' has been marked read");
}
void onWdtRanToCompletion(object sender, EventArgs e)
{
if (e is CustomEventArgs ePlus)
{
Console.WriteLine($"Expired: {_stopWatch.Elapsed}");
Console.WriteLine($"The email with the ID '{ePlus.Id}' has been marked read");
}
}
void BringConsoleToFront()
{
SetForegroundWindow(GetConsoleWindow());
}
#endregion L o c a l F x
}
[DllImport("kernel32.dll", ExactSpelling = true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
class CustomEventArgs : EventArgs
{
public CustomEventArgs(int id)
{
Id = id;
}
public int Id { get; }
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 was computed. 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 was computed. 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 was computed. |
| .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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.3.0-beta | 1 | 10/4/2024 |
| 1.2.1-beta | 1 | 11/7/2023 |
| 1.1.0 | 2 | 3/10/2023 |
| 1.0.2 | 2 | 11/7/2023 |