diff --git a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerCSharp.csproj b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerCSharp.csproj index 91b464afea..dfb40caafc 100644 --- a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerCSharp.csproj +++ b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerCSharp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable diff --git a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerMethods.cs b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerMethods.cs index 3d5aff4106..6466bda710 100644 --- a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerMethods.cs +++ b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/PeriodicTimerMethods.cs @@ -46,7 +46,7 @@ private async Task RandomArrayTimerAsync() Console.WriteLine(item); } - Console.WriteLine($"Created {numberOfArrays++} arrays in {stopWatch.Elapsed.Seconds}s"); + Console.WriteLine($"Created {numberOfArrays++} arrays in {stopWatch.Elapsed.TotalSeconds:F1}s"); Console.WriteLine(DateTime.Now.ToString("O")); } } @@ -65,6 +65,7 @@ public async Task StopTaskAsync() _cancellationToken.Cancel(); await _task; _cancellationToken.Dispose(); + _periodicTimer.Dispose(); Console.WriteLine("The array task was canceled"); } } \ No newline at end of file diff --git a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/Program.cs b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/Program.cs index 97686b45ef..d87920a7b6 100644 --- a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/Program.cs +++ b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharp/Program.cs @@ -6,7 +6,7 @@ var timerTask = new PeriodicTimerMethods(TimeSpan.FromSeconds(1), numOfElements); timerTask.Start(); -Console.WriteLine("Press any button to terminate the task"); +Console.WriteLine("Press any key to stop the task"); Console.ReadKey(); await timerTask.StopTaskAsync(); \ No newline at end of file diff --git a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerBehaviorTests.cs b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerBehaviorTests.cs new file mode 100644 index 0000000000..1ba04d7b63 --- /dev/null +++ b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerBehaviorTests.cs @@ -0,0 +1,61 @@ +using Microsoft.Extensions.Time.Testing; + +namespace PeriodicTimerCSharpTests; + +[TestClass] +public class PeriodicTimerBehaviorTests +{ + [TestMethod] + public async Task GivenMissedTicks_WhenWeWaitAgain_ThenTheyCollapseIntoOne() + { + var time = new FakeTimeProvider(); + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1), time); + + time.Advance(TimeSpan.FromSeconds(3.5)); + + Assert.IsTrue(await timer.WaitForNextTickAsync()); + + var nextTick = timer.WaitForNextTickAsync(); + Assert.IsFalse(nextTick.IsCompleted); + + time.Advance(TimeSpan.FromSeconds(0.5)); + Assert.IsTrue(await nextTick); + } + + [TestMethod] + public void GivenAWaitInFlight_WhenWeWaitTwice_ThenTheSecondCallThrows() + { + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1)); + + _ = timer.WaitForNextTickAsync(); + + Assert.ThrowsExactly(() => timer.WaitForNextTickAsync()); + } + + [TestMethod] + public async Task GivenAWaitInFlight_WhenWeDisposeTheTimer_ThenTheWaitReturnsFalse() + { + var timer = new PeriodicTimer(TimeSpan.FromSeconds(1)); + var tick = timer.WaitForNextTickAsync(); + + timer.Dispose(); + + Assert.IsFalse(await tick); + } + + [TestMethod] + public void GivenANewPeriod_WhenTimePasses_ThenTheTimerTicksOnTheNewSchedule() + { + var time = new FakeTimeProvider(); + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1), time); + + timer.Period = TimeSpan.FromSeconds(5); + var tick = timer.WaitForNextTickAsync(); + + time.Advance(TimeSpan.FromSeconds(4)); + Assert.IsFalse(tick.IsCompleted); + + time.Advance(TimeSpan.FromSeconds(1)); + Assert.IsTrue(tick.IsCompleted); + } +} diff --git a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerCSharpTests.csproj b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerCSharpTests.csproj index d6c9824ded..ff1b110f69 100644 --- a/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerCSharpTests.csproj +++ b/threads-csharp/PeriodicTimerCSharp/PeriodicTimerCSharpTests/PeriodicTimerCSharpTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -10,10 +10,11 @@ - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive