private async Task SimulateRequestsAsync(CustomerThrottle ctRate, ThrottledFunctionExecutor <TestRequest, TestResponse> tfe, TestCounter counter, CancellationToken cancellationToken) { try { while (true) { var response = await tfe.ExecuteThrottledAsync(ctRate, new TestRequest()).ConfigureAwait(false); counter.Add(); cancellationToken.ThrowIfCancellationRequested(); } } catch (OperationCanceledException) { } catch (Exception) { throw; } }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task ChangingRateTest1() #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { Func <TestRequest, CancellationToken, Task <TestResponse> > testDelegateFunction = async(req, token) => { return(await Task.Run(() => { return new TestResponse(); }).ConfigureAwait(false)); }; // customer 1: Initially 1 request per second CustomerThrottle customerThrottle1rate1 = CustomerThrottle.Create("1", 1); // ... then 60 request per second CustomerThrottle customerThrottle1rate2 = CustomerThrottle.Create("1", 60); TestCounter testCounter1 = new TestCounter(); CancellationTokenSource tfeTokenSource = new CancellationTokenSource(); using (ThrottledFunctionExecutor <TestRequest, TestResponse> tfe = new ThrottledFunctionExecutor <TestRequest, TestResponse> (testDelegateFunction, tfeTokenSource.Token)) { CancellationTokenSource cts1 = new CancellationTokenSource(); CancellationTokenSource cts2 = new CancellationTokenSource(); var t1 = new Task(async() => { await SimulateRequestsAsync(customerThrottle1rate1, tfe, testCounter1, cts1.Token).ConfigureAwait(false); }); var t2 = new Task(async() => { await SimulateRequestsAsync(customerThrottle1rate2, tfe, testCounter1, cts2.Token).ConfigureAwait(false); return; }); Stopwatch sw1 = new Stopwatch(); Stopwatch sw2 = new Stopwatch(); t1.Start(); sw1.Start(); while (true) { Thread.Sleep(1); if (sw1.Elapsed.TotalMilliseconds >= 59750) { break; } } testCounter1.stopCount = true; sw1.Stop(); cts1.Cancel(); Task.WaitAll(t1); t2.Start(); sw2.Start(); testCounter1.stopCount = false; while (true) { Thread.Sleep(1); if (sw2.Elapsed.TotalMilliseconds >= 59750) { break; } } testCounter1.stopCount = true; sw2.Stop(); cts2.Cancel(); Task.WaitAll(t2); // Total requests = 60 + 3600 = 3660 // Total seconds = ~119.5 // r/s = 30.63 TimeSpan totalElapsed = sw1.Elapsed + sw2.Elapsed; Assert.AreEqual(30.63, testCounter1.count / totalElapsed.TotalSeconds, 0.75); } }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task ThrottlingRateOver2MinutesTest1() #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { Func <TestRequest, CancellationToken, Task <TestResponse> > testDelegateFunction = async(req, token) => { return(await Task.Run(() => { return new TestResponse(); }).ConfigureAwait(false)); }; // customer 1: 1 request per second CustomerThrottle customerThrottle1 = CustomerThrottle.Create("1", 1); // customer 2: 2 requests per second CustomerThrottle customerThrottle2 = CustomerThrottle.Create("2", 2); // customer 3: 4 requests per second CustomerThrottle customerThrottle3 = CustomerThrottle.Create("3", 4); // customer 4: 120 requests per second CustomerThrottle customerThrottle4 = CustomerThrottle.Create("4", 120); TestCounter testCounter1 = new TestCounter(); TestCounter testCounter2 = new TestCounter(); TestCounter testCounter3 = new TestCounter(); TestCounter testCounter4 = new TestCounter(); CancellationTokenSource tokenSource = new CancellationTokenSource(); using (ThrottledFunctionExecutor <TestRequest, TestResponse> tfe = new ThrottledFunctionExecutor <TestRequest, TestResponse> (testDelegateFunction, tokenSource.Token)) { var t1 = new Task(async() => { await SimulateRequestsAsync(customerThrottle1, tfe, testCounter1).ConfigureAwait(false); }); var t2 = new Task(async() => { await SimulateRequestsAsync(customerThrottle2, tfe, testCounter2).ConfigureAwait(false); return; }); var t3 = new Task(async() => { await SimulateRequestsAsync(customerThrottle3, tfe, testCounter3).ConfigureAwait(false); return; }); var t4 = new Task(async() => { await SimulateRequestsAsync(customerThrottle4, tfe, testCounter4).ConfigureAwait(false); return; }); Stopwatch sw = new Stopwatch(); sw.Start(); t1.Start(); t2.Start(); t3.Start(); t4.Start(); while (true) { Thread.Sleep(1); if (sw.Elapsed.TotalMilliseconds >= 59950) { break; } } testCounter1.stopCount = true; testCounter2.stopCount = true; testCounter3.stopCount = true; testCounter4.stopCount = true; sw.Stop(); tokenSource.Cancel(); Task.WaitAll(t1, t2, t3, t4); // customer 1: 1 request per second Assert.AreEqual(1, testCounter1.count / sw.Elapsed.TotalSeconds, 0.05); // customer 2: 2 requests per second Assert.AreEqual(2, testCounter2.count / sw.Elapsed.TotalSeconds, 0.10); // customer 3: 4 requests per second Assert.AreEqual(4, testCounter3.count / sw.Elapsed.TotalSeconds, 0.4); // customer 4: 120 requests per second Assert.AreEqual(120, testCounter4.count / sw.Elapsed.TotalSeconds, 12); } }