public void Throttle_CanPreventConcurrentRequests() { // no more than 2 concurrent threads. ThrottleConfiguration configuration = new ThrottleConfiguration { MaxConcurrentThreads = 2 }; Throttle throttle = new Throttle(configuration); Task[] threads = new Task[5]; ManualResetEvent awaiter = new ManualResetEvent(false); CancellationTokenSource outerCancellationSource = new CancellationTokenSource(5 * 1000); // 5 seconds long success = 0; for (int i = 0; i < threads.Length; i++) { int instance = i; Stopwatch sw = new Stopwatch(); sw.Start(); threads[i] = Task.Run(async() => { CancellationTokenSource innerCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( outerCancellationSource.Token, new CancellationTokenSource(5 * 1000).Token // 5 seconds ); Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread activated (activateTime: {sw.Elapsed})"); sw.Restart(); awaiter.WaitOne(); Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread started (runTime: {sw.Elapsed})"); try { IDisposable lease = await throttle.AcquireLeaseAsync(innerCancellationSource.Token); using (lease) { Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: acquired lease (threads: {throttle.ActiveThreads}, runTime: {sw.Elapsed})"); await Task.Delay(1000, innerCancellationSource.Token); // do some work Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: completed work (runTime: {sw.Elapsed})"); Assert.True(throttle.ActiveThreads <= configuration.MaxConcurrentThreads, $"Instance {instance}: Thread count exceeds max concurrent threads (actual: {throttle.ActiveThreads}, max: {configuration.MaxConcurrentThreads})"); } long current = Interlocked.Increment(ref success); Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread complete (runTime: {sw.Elapsed}, success: {current})"); } catch (Exception ex) { Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread failed (runTime: {sw.Elapsed}) {ex}"); throw new Exception("Operation failed", ex); } }); } Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] set....."); awaiter.Set(); Task.WaitAll(threads, outerCancellationSource.Token); Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] complete....."); long actual = Interlocked.Read(ref success); Assert.Equal(threads.Length, actual); }