public void TestStress() { #region Initialization object lockObject = new object(); Timeout timeout = new Timeout(null); TimeoutTask[] tasks; timeout = new Timeout(lockObject); tasks = new TimeoutTask[10]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = new TimeoutTask(); timeout.Now = 1000 + i * 100; timeout.Schedule(tasks[i]); } timeout.Now = 100; #endregion int LOOP = 500; bool[] running = new bool[] { true }; int[] count = new int[] { 0, 0, 0 }; timeout.Now = (DateTime.UtcNow.Ticks / 1000); timeout.Duration = 500; // Start a ticker thread that will tick over the timer frequently. System.Threading.Thread ticker = new System.Threading.Thread( new System.Threading.ThreadStart( () => { while (running[0]) { try { // use lock.wait so we have a memory barrier and // have no funny optimisation issues. lock (lockObject) { System.Threading.Monitor.Wait(lockObject, 30); } System.Threading.Thread.Sleep(30); timeout.Tick((DateTime.UtcNow.Ticks / 1000)); } catch (Exception e) { Console.Error.WriteLine(e.StackTrace); } } } ) ); ticker.Start(); // start lots of test threads for (int i = 0; i < LOOP; i++) { // System.Threading.Thread th = new System.Threading.Thread( new System.Threading.ThreadStart( () => { // count how many threads were started (should == LOOP) lock (count) { count[0]++; } // create a task for this thread TimeoutTask task = new TimeoutTask1(count); // this thread will loop and each loop with schedule a // task with a delay on top of the timeouts duration // mostly this thread will then cancel the task // But once it will wait and the task will expire int once = (int)(10 + ((DateTime.UtcNow.Ticks / 1000) % 50)); // do the looping until we are stopped int loop = 0; while (running[0]) { try { long delay = 1000; long wait = 100 - once; if (loop++ == once) { // THIS loop is the one time we wait 1000ms lock (count) { count[1]++; } delay = 200; wait = 1000; } timeout.Schedule(task, delay); // do the wait System.Threading.Thread.Sleep((int)wait); // cancel task (which may have expired) task.Cancel(); } catch (Exception e) { Console.Error.WriteLine(e.StackTrace); } } } )); th.Start(); } // run test for 5s System.Threading.Thread.Sleep(8000); lock (lockObject) { running[0] = false; } // give some time for test to stop System.Threading.Thread.Sleep(2000); timeout.Tick((DateTime.UtcNow.Ticks / 1000)); System.Threading.Thread.Sleep(1000); // check the counts Assert.AreEqual(LOOP, count[0], "count threads"); Assert.AreEqual(LOOP, count[1], "count once waits"); Assert.AreEqual(LOOP, count[2], "count expires"); }