public async Task ManyWaitsStackUp() { await Policy .Handle <ShouldAssertException>() .RetryAsync(3) .ExecuteAsync(async() => { // arrange var limiter = new Limiter(new Limit(10), 5); using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // act while (cancellation.IsCancellationRequested == false) { var task = limiter.WaitAsync(cancellation.Token); if (!task.IsCompleted) { await task.ConfigureAwait(false); break; } } var delayOne = new Stopwatch(); delayOne.Start(); var delayTwo = new Stopwatch(); delayTwo.Start(); var delayThree = new Stopwatch(); delayThree.Start(); var waits = new List <Task> { limiter.WaitAsync(cancellation.Token), limiter.WaitAsync(cancellation.Token), limiter.WaitAsync(cancellation.Token), }; var taskOne = await Task.WhenAny(waits.ToArray()).ConfigureAwait(false); await taskOne.ConfigureAwait(false); delayOne.Stop(); waits.Remove(taskOne); var taskTwo = await Task.WhenAny(waits.ToArray()).ConfigureAwait(false); await taskTwo.ConfigureAwait(false); delayTwo.Stop(); waits.Remove(taskTwo); var taskThree = await Task.WhenAny(waits.ToArray()).ConfigureAwait(false); await taskThree.ConfigureAwait(false); delayThree.Stop(); waits.Remove(taskThree); // assert delayOne.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(100), tolerance: TimeSpan.FromMilliseconds(25)); delayTwo.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(200), tolerance: TimeSpan.FromMilliseconds(25)); delayThree.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(300), tolerance: TimeSpan.FromMilliseconds(25)); }).ConfigureAwait(false); }
public async Task WaitAsyncCausesPauseLikeReserve() { // arrange var limiter = new Limiter(new Limit(10), 5); using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // act while (cancellation.IsCancellationRequested == false) { var task = limiter.WaitAsync(cancellation.Token); if (!task.IsCompleted) { await task.ConfigureAwait(false); break; } } var delayOne = new Stopwatch(); delayOne.Start(); await limiter.WaitAsync(cancellation.Token).ConfigureAwait(false); delayOne.Stop(); var delayTwoMore = new Stopwatch(); delayTwoMore.Start(); await limiter.WaitAsync(2, cancellation.Token).ConfigureAwait(false); delayTwoMore.Stop(); await Task.Delay(TimeSpan.FromMilliseconds(150)).ConfigureAwait(false); var delayAlreadyAvailable = new Stopwatch(); delayAlreadyAvailable.Start(); await limiter.WaitAsync(cancellation.Token).ConfigureAwait(false); delayAlreadyAvailable.Stop(); var delayHalfAvailable = new Stopwatch(); delayHalfAvailable.Start(); await limiter.WaitAsync(cancellation.Token).ConfigureAwait(false); delayHalfAvailable.Stop(); // assert delayOne.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(100), tolerance: TimeSpan.FromMilliseconds(25)); delayTwoMore.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(200), tolerance: TimeSpan.FromMilliseconds(25)); delayAlreadyAvailable.Elapsed.ShouldBe(TimeSpan.Zero, tolerance: TimeSpan.FromMilliseconds(5)); delayHalfAvailable.Elapsed.ShouldBe(TimeSpan.FromMilliseconds(50), tolerance: TimeSpan.FromMilliseconds(25)); }