public void Invokes_Only_One_Action_At_A_Time() { var it = new InvocationThrottle(min: TimeSpan.FromMilliseconds(1), max: TimeSpan.FromMilliseconds(2)); int im_doing_stuff = 0; bool hasException = false; int invocation_count = 0; ConcurrentBag<AutoResetEvent> ares = new ConcurrentBag<AutoResetEvent>(); // invoke action in a look for (int i = 0; i < 10; i++) { var local_i = i; // some actions will be cancelled bevause min time has not passed // those should never even start running // there always should be at most one action running at a tim it.InvokeAsync(() => { var are = new AutoResetEvent(initialState: false); ares.Add(are); try { Interlocked.Increment(ref invocation_count); LongAction(ref im_doing_stuff); // given min of 1s, this should be invoked only once if(local_i < 9 && invocation_count != 1) { throw new Exception(); } } catch(Exception ex) { hasException = true; } are.Set(); }); Thread.Sleep(1); } Thread.Sleep(200); OnMtaThread(() => AutoResetEvent.WaitAll(ares.ToArray())); if (hasException) Assert.Fail(); }
public void InvokesOnlyOneAtTheTimeAndLastOneWins() { var it = new InvocationThrottle(min: TimeSpan.FromMilliseconds(1), max: TimeSpan.FromMilliseconds(2)); int im_doing_stuff = 0; bool hasException = false; int invocation_count = 0; ConcurrentBag<AutoResetEvent> ares = new ConcurrentBag<AutoResetEvent>(); for (int i = 0; i < 10; i++) { var local_i = i; it.Invoke(() => { var are = new AutoResetEvent(initialState: false); ares.Add(are); try { Interlocked.Increment(ref invocation_count); LongAction(ref im_doing_stuff); if((local_i < 9 && invocation_count != 1) || (local_i == 9 && invocation_count != 2)) { throw new Exception(); } } catch(Exception ex) { hasException = true; } are.Set(); }); Thread.Sleep(1); } Thread.Sleep(200); OnMtaThread(() => AutoResetEvent.WaitAll(ares.ToArray())); if (hasException) Assert.Fail(); }
public void ActionIsInvokedOnDifferentThread() { var it = new InvocationThrottle(TimeSpan.MinValue); var are = new AutoResetEvent(initialState: false); var tid = Thread.CurrentThread.ManagedThreadId; it.Invoke(() => { Assert.AreNotEqual(tid, Thread.CurrentThread.ManagedThreadId); are.Set(); }); are.WaitOne(); Assert.IsTrue(true); }
public void WaitsMinTimespanBeforeExecuting() { var min = TimeSpan.FromMilliseconds(100); var it = new InvocationThrottle(min); var tid = Thread.CurrentThread.ManagedThreadId; var are = new AutoResetEvent(initialState: false); it.Invoke(() => { Assert.AreNotEqual(tid, Thread.CurrentThread.ManagedThreadId); are.Set(); }); var sw = Stopwatch.StartNew(); are.WaitOne(); sw.Stop(); Assert.IsTrue(sw.Elapsed.TotalMilliseconds >= min.TotalMilliseconds); }
public void MultipleRequestsForInvocationDelayActualInvocationUntilMaxTimespanElapsed() { var min = TimeSpan.FromMilliseconds(100); var max = TimeSpan.FromMilliseconds(500); var it = new InvocationThrottle(min, max); var tid = Thread.CurrentThread.ManagedThreadId; var are = new AutoResetEvent(initialState: false); var t = new Task(() => { bool keep_going = true; while(keep_going) { it.Invoke(() => { Assert.AreNotEqual(tid, Thread.CurrentThread.ManagedThreadId); are.Set(); keep_going = false; }); } }); var sw = Stopwatch.StartNew(); t.Start(); are.WaitOne(); sw.Stop(); Trace.WriteLine(sw.Elapsed.TotalMilliseconds + " , " + max.TotalMilliseconds); Assert.IsTrue(sw.Elapsed.TotalMilliseconds >= max.TotalMilliseconds); }
public void MyTestMethod() { var min = TimeSpan.FromMilliseconds(50); var it = new InvocationThrottle(min); var tid = Thread.CurrentThread.ManagedThreadId; int invocation_count = 0; for (int i = 1; i <= 2; i++) { var sw = Stopwatch.StartNew(); if(i == 2) { } it.InvokeAsync(() => { Interlocked.Increment(ref invocation_count); sw.Stop(); Assert.AreNotEqual(tid, Thread.CurrentThread.ManagedThreadId); if(invocation_count == 1) throw new Exception(); }); Thread.Sleep(75); } Thread.Sleep(1000); Assert.AreEqual(2, invocation_count); }
public void Waits_Min_Before_Executing() { var min = TimeSpan.FromMilliseconds(50); var it = new InvocationThrottle(min); var tid = Thread.CurrentThread.ManagedThreadId; for (int i = 1; i <= 2; i++) { var are = new AutoResetEvent(initialState: false); var sw = Stopwatch.StartNew(); it.InvokeAsync(() => { sw.Stop(); Assert.AreNotEqual(tid, Thread.CurrentThread.ManagedThreadId); are.Set(); }); are.WaitOne(); // wait so that next request is not throttled, but initial delay should still apply Thread.Sleep(100); Assert.IsTrue(sw.Elapsed.TotalMilliseconds >= min.TotalMilliseconds, "failed iteration {0}, elapse: {1}".FormatWith(i.ToString(), sw.Elapsed.TotalMilliseconds)); } }
public void Does_Not_Invoke_Actions_Before_Min_Passed() { var it = new InvocationThrottle(TimeSpan.FromMilliseconds(50), TimeSpan.FromMilliseconds(100)); var failed = false; var sw = Stopwatch.StartNew(); var are = new AutoResetEvent(false); for(int i = 0; i < 100; i++) { it.InvokeAsync((ct) => { sw.Stop(); var _i = i; if (_i != 100) failed = true; are.Set(); }); } are.WaitOne(); if (failed) Assert.Fail(); Assert.IsTrue(sw.Elapsed.TotalMilliseconds > 50); }
public void Multiple_Requests_For_Invocation_Delay_Actual_Invocation_Until_Max_Timespan_Elapsed() { var min = TimeSpan.FromMilliseconds(50); var max = TimeSpan.FromMilliseconds(250); var it = new InvocationThrottle(min, max); var tid = Thread.CurrentThread.ManagedThreadId; var start_time = DateTime.UtcNow; var invocation_time = DateTime.UtcNow; var should_break = false; while (!should_break && (DateTime.UtcNow - start_time).TotalMilliseconds < 1000) { it.InvokeAsync((ct) => { if (ct.IsCancellationRequested) return; invocation_time = DateTime.UtcNow; should_break = true; }); } Assert.IsTrue((invocation_time - start_time).TotalMilliseconds >= 250); Assert.IsTrue((invocation_time - start_time).TotalMilliseconds < 500); }