public static bool ExternalCancel_GetConsumingEnumerable() { TestHarness.TestLog("* BlockingCollectionCancellationTests.ExternalCancel_GetConsumingEnumerable()"); bool passed = true; BlockingCollection <int> bc = new BlockingCollection <int>(); CancellationTokenSource cs = new CancellationTokenSource(); ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(100); cs.Cancel(); }); IEnumerable <int> enumerable = bc.GetConsumingEnumerable(cs.Token); passed &= TestHarnessAssert.IsFalse(cs.IsCancellationRequested, "At this point the cancel should not have occurred."); passed &= TestHarnessAssert.EnsureOperationCanceledExceptionThrown( () => enumerable.GetEnumerator().MoveNext(), cs.Token, "The operation should wake up via token cancellation."); return(passed); }
public static bool ExternalCancel_TryAddToAny() { TestHarness.TestLog("* BlockingCollectionCancellationTests.ExternalCancel_AddToAny()"); bool passed = true; BlockingCollection <int> bc1 = new BlockingCollection <int>(1); BlockingCollection <int> bc2 = new BlockingCollection <int>(1); bc1.Add(1); //fill the bc. bc2.Add(1); //fill the bc. CancellationTokenSource cs = new CancellationTokenSource(); ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(100); cs.Cancel(); }); passed &= TestHarnessAssert.IsFalse(cs.IsCancellationRequested, "At this point the cancel should not have occurred."); passed &= TestHarnessAssert.EnsureOperationCanceledExceptionThrown( () => BlockingCollection <int> .TryAddToAny(new[] { bc1, bc2 }, 1, 10000, cs.Token), cs.Token, "The operation should wake up via token cancellation."); return(passed); }
public static bool ExternalCancel_TryTake() { TestHarness.TestLog("* BlockingCollectionCancellationTests.ExternalCancel_TryTake()"); bool passed = true; BlockingCollection <int> bc = new BlockingCollection <int>(); //empty collection. CancellationTokenSource cs = new CancellationTokenSource(); ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(100); cs.Cancel(); }); int item; passed &= TestHarnessAssert.IsFalse(cs.IsCancellationRequested, "At this point the cancel should not have occurred."); passed &= TestHarnessAssert.EnsureOperationCanceledExceptionThrown( () => bc.TryTake(out item, 100000, cs.Token), cs.Token, "The operation should wake up via token cancellation."); return(passed); }
//This tests that Take/TryTake wake up correctly if CompleteAdding() is called while the taker is waiting. public static bool InternalCancellation_WakingUpTake() { TestHarness.TestLog("* BlockingCollectionCancellationTests.InternalCancellation_WakingUpTake()"); bool passed = true; BlockingCollection <int> coll1 = new BlockingCollection <int>(); ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(500); coll1.CompleteAdding(); }); //call Take.. it should wake up with an OCE. when CompleteAdding() is called. passed &= TestHarnessAssert.IsFalse(coll1.IsAddingCompleted, "(1) At this point CompleteAdding should not have occurred."); passed &= TestHarnessAssert.EnsureExceptionThrown( () => coll1.Take(), typeof(InvalidOperationException), "an IOE should be thrown if CompleteAdding occurs during blocking Take()"); return(passed); }
//This tests that Take/TryTake wake up correctly if CompleteAdding() is called while the taker is waiting. public static bool InternalCancellation_WakingUpTryTake() { TestHarness.TestLog("* BlockingCollectionCancellationTests.InternalCancellation_WakingUpTryTake()"); bool passed = true; BlockingCollection <int> coll1 = new BlockingCollection <int>(); ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(500); coll1.CompleteAdding(); }); int item; passed &= TestHarnessAssert.IsFalse(coll1.IsAddingCompleted, "At this point CompleteAdding should not have occurred."); bool tookItem = coll1.TryTake(out item, 1000000); // wait essentially indefinitely. 1000seconds. passed &= TestHarnessAssert.IsFalse(tookItem, "TryTake should wake up with tookItem=false."); return(passed); }
//This tests that TryAdd wake up correctly if CompleteAdding() is called while the taker is waiting. public static bool InternalCancellation_WakingUpTryAdd() { TestHarness.TestLog("* BlockingCollectionCancellationTests.InternalCancellation_WakingUpTryAdd()"); bool passed = true; BlockingCollection <int> coll1 = new BlockingCollection <int>(1); coll1.Add(1); //fills the collection. ThreadPool.QueueUserWorkItem( (obj) => { Thread.Sleep(500); coll1.CompleteAdding(); }); passed &= TestHarnessAssert.IsFalse(coll1.IsAddingCompleted, "At this point CompleteAdding should not have occurred."); passed &= TestHarnessAssert.EnsureExceptionThrown( () => coll1.TryAdd(1, 1000000), //an indefinite wait to add.. 1000 seconds. typeof(InvalidOperationException), "an InvalidOpEx should be thrown if CompleteAdding occurs during blocking Add()"); return(passed); }
//Identified as a possible concern in bug 544743. private static bool SemaphoreSlim_MultipleWaitersWithSeparateTokens() { TestHarness.TestLog("* SemaphoreSlimCancellationTests.SemaphoreSlim_MultipleWaitersWithSeparateTokens()"); bool passed = true; SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0); // this semaphore will always be blocked for waiters. const int waitTimeoutMilliseconds = 1000; const int waitBeforeCancelMilliseconds = 300; CancellationTokenSource cts1 = new CancellationTokenSource(); CancellationTokenSource cts2 = new CancellationTokenSource(); bool wait1WokeUpNormally = false; bool wait2WokeUpNormally = false; OperationCanceledException wait1OCE = null; OperationCanceledException wait2OCE = null; int wait1ElapsedMilliseconds = -1; int wait2ElapsedMilliseconds = -1; CountdownEvent cde_allThreadsFinished = new CountdownEvent(2); //Queue up cancellation of CTS1. ThreadPool.QueueUserWorkItem( unused => { Thread.Sleep(waitBeforeCancelMilliseconds); // wait a little while. cts1.Cancel(); } ); //Queue up a wait on mres(CTS1) ThreadPool.QueueUserWorkItem( unused => { Stopwatch sw = Stopwatch.StartNew(); try { wait1WokeUpNormally = semaphoreSlim.Wait(waitTimeoutMilliseconds, cts1.Token); } catch (OperationCanceledException oce) { wait1OCE = oce; } finally { sw.Stop(); } wait1ElapsedMilliseconds = (int)sw.Elapsed.TotalMilliseconds; cde_allThreadsFinished.Signal(); } ); //Queue up a wait on mres(CTS2) ThreadPool.QueueUserWorkItem( unused => { Stopwatch sw = Stopwatch.StartNew(); try { wait2WokeUpNormally = semaphoreSlim.Wait(waitTimeoutMilliseconds, cts2.Token); } catch (OperationCanceledException oce) { wait2OCE = oce; } finally { sw.Stop(); } wait2ElapsedMilliseconds = (int)sw.Elapsed.TotalMilliseconds; cde_allThreadsFinished.Signal(); } ); cde_allThreadsFinished.Wait(); Console.WriteLine(" (first wait duration [expecting <={0,4}] ={1,4})", 500, wait1ElapsedMilliseconds); Console.WriteLine(" (second wait duration [expecting {0,4} +-50ms] ={1,4})", waitTimeoutMilliseconds, wait2ElapsedMilliseconds); passed &= TestHarnessAssert.IsFalse(wait1WokeUpNormally, "The first wait should be canceled."); passed &= TestHarnessAssert.IsNotNull(wait1OCE, "The first wait should have thrown an OCE."); passed &= TestHarnessAssert.AreEqual(cts1.Token, OCEHelper.ExtractCT(wait1OCE), "The first wait should have thrown an OCE(cts1.token)."); passed &= TestHarnessAssert.IsTrue(wait1ElapsedMilliseconds < 500, "[Warning: Timing Sensitive Test] The first wait should have canceled before 500ms elapsed."); passed &= TestHarnessAssert.IsFalse(wait2WokeUpNormally, "The second wait should not have woken up normally. It should have woken due to timeout."); passed &= TestHarnessAssert.IsNull(wait2OCE, "The second wait should not have thrown an OCE."); passed &= TestHarnessAssert.IsTrue(950 <= wait2ElapsedMilliseconds && wait2ElapsedMilliseconds <= 1050, "[Warning: Timing Sensitive Test] The second wait should have waited 1000ms +-50ms). Actual wait duration = " + wait2ElapsedMilliseconds); return(passed); }