diff --git a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay.Test/ThreadSleepVsTaskDelay.Test.csproj b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay.Test/ThreadSleepVsTaskDelay.Test.csproj index 4d1afdba67..32572b642a 100644 --- a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay.Test/ThreadSleepVsTaskDelay.Test.csproj +++ b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay.Test/ThreadSleepVsTaskDelay.Test.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable diff --git a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/Program.cs b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/Program.cs index c6b0fcc160..c13129f575 100644 --- a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/Program.cs +++ b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/Program.cs @@ -1,32 +1,84 @@ -using System.Diagnostics; +using System.Diagnostics; -namespace ThreadSleepVsTaskDelay +namespace ThreadSleepVsTaskDelay; + +public class Program { - public class Program + public static async Task UseTaskDelay(int delayMilliseconds = 2000) + { + Console.WriteLine($"Before delay: Thread id = {Environment.CurrentManagedThreadId}"); + await Task.Delay(delayMilliseconds); + Console.WriteLine($"After delay: Thread id = {Environment.CurrentManagedThreadId}"); + } + + public static void UseThreadSleep(int sleepMilliseconds = 2000) + { + Console.WriteLine($"Before sleep: Thread id = {Environment.CurrentManagedThreadId}"); + Thread.Sleep(sleepMilliseconds); + Console.WriteLine($"After sleep: Thread id = {Environment.CurrentManagedThreadId}"); + } + + public static async Task RunBlockingWorkAsync(int workItems, int milliseconds) + { + var stopwatch = Stopwatch.StartNew(); + var blocking = Enumerable.Range(0, workItems) + .Select(_ => Task.Run(() => Thread.Sleep(milliseconds))); + + await Task.WhenAll(blocking); + + return stopwatch.ElapsedMilliseconds; + } + + public static async Task RunNonBlockingWorkAsync(int workItems, int milliseconds) + { + var stopwatch = Stopwatch.StartNew(); + var waiting = Enumerable.Range(0, workItems) + .Select(_ => Task.Delay(milliseconds)); + + await Task.WhenAll(waiting); + + return stopwatch.ElapsedMilliseconds; + } + + private static async Task RefreshCacheAsync() { - public static async Task UseTaskDelay(int sleepMilliseconds = 2000) + await Task.Delay(50); + } + + public static async Task RunPeriodicRefreshAsync(CancellationToken cancellationToken) + { + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1)); + + while (await timer.WaitForNextTickAsync(cancellationToken)) { - Console.WriteLine($"Before delay: Thread id = {Environment.CurrentManagedThreadId}"); - await Task.Delay(sleepMilliseconds); - Console.WriteLine($"After delay: Thread id = {Environment.CurrentManagedThreadId}"); + await RefreshCacheAsync(); // runs every second, no drift, cancellable } + } + + private static async Task Main() + { + Console.WriteLine("Starting Thread.Sleep test..."); + UseThreadSleep(); + Console.WriteLine("Thread.Sleep test completed.\n"); + + Console.WriteLine("Starting Task.Delay test..."); + await UseTaskDelay(); + Console.WriteLine("Task.Delay test completed.\n"); - public static void UseThreadSleep(int delayMilliseconds = 2000) + Console.WriteLine($"Processor count: {Environment.ProcessorCount}"); + var blockingMs = await RunBlockingWorkAsync(50, 1000); + Console.WriteLine($"50 blocking items: {blockingMs} ms"); + var nonBlockingMs = await RunNonBlockingWorkAsync(50, 1000); + Console.WriteLine($"50 non-blocking items: {nonBlockingMs} ms"); + + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3.5)); + try { - Console.WriteLine($"Before sleep: Thread id = {Environment.CurrentManagedThreadId}"); - Thread.Sleep(delayMilliseconds); - Console.WriteLine($"After sleep: Thread id = {Environment.CurrentManagedThreadId}"); + await RunPeriodicRefreshAsync(cts.Token); } - - private static async Task Main() + catch (OperationCanceledException) { - Console.WriteLine("Starting Thread.Sleep test..."); - UseThreadSleep(); - Console.WriteLine("Thread.Sleep test completed.\n"); - - Console.WriteLine("Starting Task.Delay test..."); - await UseTaskDelay(); - Console.WriteLine("Task.Delay test completed."); + Console.WriteLine("Periodic refresh canceled."); } } } diff --git a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/ThreadSleepVsTaskDelay.csproj b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/ThreadSleepVsTaskDelay.csproj index fbb4a9b9a4..5de8ecb546 100644 --- a/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/ThreadSleepVsTaskDelay.csproj +++ b/threads-csharp/ThreadSleepVsTaskDelay/src/ThreadSleepVsTaskDelay/ThreadSleepVsTaskDelay.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable true