public async Task CancellationTestCase4() { CancellationTokenSource instanceCancellationTokenSource = new CancellationTokenSource(); CancellationToken instanceCancellationToken = instanceCancellationTokenSource.Token; CancellationTokenSource delegateCancellationTokenSource = new CancellationTokenSource(); CancellationToken delegateCancellationToken = delegateCancellationTokenSource.Token; TaskCompletionSource <bool> taskCompletionSourceSetWhenDelegateRuns = new TaskCompletionSource <bool>(); Func <TaskCompletionSource <bool>, CancellationToken, Task <TestResponse> > funcWhichIsAFairlyLongRunningTask = async(req, token) => { req.SetResult(true); await Task.Delay(TimeSpan.FromMinutes(3).Duration(), token).ConfigureAwait(false); return(new TestResponse()); }; using (ThrottledFunctionExecutor <TaskCompletionSource <bool>, TestResponse> tfe = new ThrottledFunctionExecutor <TaskCompletionSource <bool>, TestResponse> (funcWhichIsAFairlyLongRunningTask, instanceCancellationToken)) { CustomerThrottle customerThrottle = CustomerThrottle.Create("ExampleKey", 1); Task <TestResponse> response = tfe.ExecuteThrottledAsync(customerThrottle, taskCompletionSourceSetWhenDelegateRuns, delegateCancellationToken); await taskCompletionSourceSetWhenDelegateRuns.Task.ConfigureAwait(false); // the delegate is running at this point, and so all of the internal cancellation logic has been cleared await Task.Delay(TimeSpan.FromSeconds(5).Duration()).ConfigureAwait(false); // just to ensure we've hit the Task.Delay in the delegate try { delegateCancellationTokenSource.Cancel(); var result = await response.ConfigureAwait(false); Assert.Fail(); // OperationCanceledException should have been thrown } catch (OperationCanceledException) { return; } catch (Exception) { Assert.Fail(); } Assert.Fail(); } }
private async Task SimulateRequestsAsync(CustomerThrottle ct, ThrottledFunctionExecutor <TestRequest, TestResponse> tfe, TestCounter counter) { try { while (true) { var response = await tfe.ExecuteThrottledAsync(ct, new TestRequest()).ConfigureAwait(false); counter.Add(); } } catch (OperationCanceledException) { } catch (Exception) { throw; } }
public async Task CancellationTestCase3() { CancellationTokenSource instanceCancellationTokenSource = new CancellationTokenSource(); CancellationToken instanceCancellationToken = instanceCancellationTokenSource.Token; CancellationTokenSource delegateCancellationTokenSource = new CancellationTokenSource(); CancellationToken delegateCancellationToken = delegateCancellationTokenSource.Token; instanceCancellationTokenSource.Cancel(); Func <TestRequest, CancellationToken, Task <TestResponse> > funcPlaceholderDelegateThatWillNeverRun = async(req, token) => { await Task.Delay(1).ConfigureAwait(false); throw new NotImplementedException(); }; using (ThrottledFunctionExecutor <TestRequest, TestResponse> tfe = new ThrottledFunctionExecutor <TestRequest, TestResponse> (funcPlaceholderDelegateThatWillNeverRun, instanceCancellationToken)) { CustomerThrottle customerThrottle = CustomerThrottle.Create("ExampleKey", 1); try { TestResponse response = await tfe.ExecuteThrottledAsync(customerThrottle, new TestRequest(), delegateCancellationToken).ConfigureAwait(false); Assert.Fail(); } catch (OperationCanceledException) { return; } catch (Exception) { Assert.Fail(); } Assert.Fail(); } }
#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); } }