public static void ConcurrentInitializeTest() { int processorCount = Environment.ProcessorCount; var countdownEvent = new CountdownEvent(processorCount); Action threadMain = () => { countdownEvent.Signal(); countdownEvent.Wait(ThreadTestHelpers.UnexpectedTimeoutMilliseconds); Assert.True(ThreadPool.SetMinThreads(processorCount, processorCount)); }; var waitForThreadArray = new Action[processorCount]; for (int i = 0; i < processorCount; ++i) { var t = ThreadTestHelpers.CreateGuardedThread(out waitForThreadArray[i], threadMain); t.IsBackground = true; t.Start(); } foreach (Action waitForThread in waitForThreadArray) { waitForThread(); } }
public static void JoinTest() { var threadReady = new ManualResetEvent(false); var continueThread = new ManualResetEvent(false); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { threadReady.Set(); continueThread.CheckedWait(); Thread.Sleep(ExpectedTimeoutMilliseconds); }); t.IsBackground = true; Assert.Throws <ArgumentOutOfRangeException>(() => t.Join(-2)); Assert.Throws <ArgumentOutOfRangeException>(() => t.Join(TimeSpan.FromMilliseconds(-2))); Assert.Throws <ArgumentOutOfRangeException>(() => t.Join(TimeSpan.FromMilliseconds((double)int.MaxValue + 1))); Assert.Throws <ThreadStateException>(() => t.Join()); Assert.Throws <ThreadStateException>(() => t.Join(UnexpectedTimeoutMilliseconds)); Assert.Throws <ThreadStateException>(() => t.Join(TimeSpan.FromMilliseconds(UnexpectedTimeoutMilliseconds))); t.Start(); threadReady.CheckedWait(); Assert.False(t.Join(ExpectedTimeoutMilliseconds)); Assert.False(t.Join(TimeSpan.FromMilliseconds(ExpectedTimeoutMilliseconds))); continueThread.Set(); waitForThread(); Assert.True(t.Join(0)); Assert.True(t.Join(TimeSpan.Zero)); }
public static void AbortSuspendTest() { var e = new ManualResetEvent(false); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, e.CheckedWait); t.IsBackground = true; Action verify = () => { Assert.Throws <PlatformNotSupportedException>(() => t.Abort()); Assert.Throws <PlatformNotSupportedException>(() => t.Abort(t)); #pragma warning disable 618 // Obsolete members Assert.Throws <PlatformNotSupportedException>(() => t.Suspend()); Assert.Throws <PlatformNotSupportedException>(() => t.Resume()); #pragma warning restore 618 // Obsolete members }; verify(); t.Start(); verify(); e.Set(); waitForThread(); Assert.Throws <PlatformNotSupportedException>(() => Thread.ResetAbort()); }
public static void StartTest() { var e = new AutoResetEvent(false); Action waitForThread; Thread t = null; t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { e.CheckedWait(); Assert.Same(t, Thread.CurrentThread); }); t.IsBackground = true; Assert.Throws <InvalidOperationException>(() => t.Start(null)); Assert.Throws <InvalidOperationException>(() => t.Start(t)); t.Start(); Assert.Throws <ThreadStateException>(() => t.Start()); e.Set(); waitForThread(); Assert.Throws <ThreadStateException>(() => t.Start()); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, parameter => e.CheckedWait()); t.IsBackground = true; t.Start(); Assert.Throws <ThreadStateException>(() => t.Start()); Assert.Throws <ThreadStateException>(() => t.Start(null)); Assert.Throws <ThreadStateException>(() => t.Start(t)); e.Set(); waitForThread(); Assert.Throws <ThreadStateException>(() => t.Start()); Assert.Throws <ThreadStateException>(() => t.Start(null)); Assert.Throws <ThreadStateException>(() => t.Start(t)); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, parameter => { Assert.Null(parameter); Assert.Same(t, Thread.CurrentThread); }); t.IsBackground = true; t.Start(); waitForThread(); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, parameter => { Assert.Null(parameter); Assert.Same(t, Thread.CurrentThread); }); t.IsBackground = true; t.Start(null); waitForThread(); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, parameter => { Assert.Same(t, parameter); Assert.Same(t, Thread.CurrentThread); }); t.IsBackground = true; t.Start(t); waitForThread(); }
public static void ManagedThreadIdTest() { var e = new ManualResetEvent(false); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, e.CheckedWait); t.IsBackground = true; t.Start(); Assert.NotEqual(Thread.CurrentThread.ManagedThreadId, t.ManagedThreadId); e.Set(); waitForThread(); }
public void TimersCreatedConcurrentlyOnDifferentThreadsAllFire() { int processorCount = Environment.ProcessorCount; int timerTickCount = 0; TimerCallback timerCallback = _ => Interlocked.Increment(ref timerTickCount); var threadStarted = new AutoResetEvent(false); var createTimers = new ManualResetEvent(false); var timers = new Timer[processorCount]; Action <object> createTimerThreadStart = data => { int i = (int)data; var sw = new Stopwatch(); threadStarted.Set(); createTimers.WaitOne(); // Use the CPU a bit around creating the timer to try to have some of these threads run concurrently sw.Restart(); do { Thread.SpinWait(1000); } while (sw.ElapsedMilliseconds < 10); timers[i] = new Timer(timerCallback, null, 1, Timeout.Infinite); // Use the CPU a bit around creating the timer to try to have some of these threads run concurrently sw.Restart(); do { Thread.SpinWait(1000); } while (sw.ElapsedMilliseconds < 10); }; var waitsForThread = new Action[timers.Length]; for (int i = 0; i < timers.Length; ++i) { var t = ThreadTestHelpers.CreateGuardedThread(out waitsForThread[i], createTimerThreadStart); t.IsBackground = true; t.Start(i); threadStarted.CheckedWait(); } createTimers.Set(); ThreadTestHelpers.WaitForCondition(() => timerTickCount == timers.Length); foreach (var waitForThread in waitsForThread) { waitForThread(); } }
public static void InterruptTest() { // Interrupting a thread that is not blocked does not do anything, but once the thread starts blocking, it gets // interrupted and does not auto-reset the signaled event var threadReady = new AutoResetEvent(false); var continueThread = new AutoResetEvent(false); bool continueThreadBool = false; Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { threadReady.Set(); ThreadTestHelpers.WaitForConditionWithoutBlocking(() => Volatile.Read(ref continueThreadBool)); threadReady.Set(); Assert.Throws <ThreadInterruptedException>(() => continueThread.CheckedWait()); }); t.IsBackground = true; t.Start(); threadReady.CheckedWait(); continueThread.Set(); t.Interrupt(); Assert.False(threadReady.WaitOne(ExpectedTimeoutMilliseconds)); Volatile.Write(ref continueThreadBool, true); waitForThread(); Assert.True(continueThread.WaitOne(0)); // Interrupting a dead thread does nothing t.Interrupt(); // Interrupting an unstarted thread causes the thread to be interrupted after it is started and starts blocking t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => Assert.Throws <ThreadInterruptedException>(() => continueThread.CheckedWait())); t.IsBackground = true; t.Interrupt(); t.Start(); waitForThread(); // A thread that is already blocked on a synchronization primitive unblocks immediately continueThread.Reset(); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => Assert.Throws <ThreadInterruptedException>(() => continueThread.CheckedWait())); t.IsBackground = true; t.Start(); ThreadTestHelpers.WaitForCondition(() => (t.ThreadState & ThreadState.WaitSleepJoin) != 0); t.Interrupt(); waitForThread(); }
public static void PriorityTest() { var e = new ManualResetEvent(false); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, e.CheckedWait); t.IsBackground = true; Assert.Equal(ThreadPriority.Normal, t.Priority); t.Priority = ThreadPriority.AboveNormal; Assert.Equal(ThreadPriority.AboveNormal, t.Priority); t.Start(); Assert.Equal(ThreadPriority.AboveNormal, t.Priority); t.Priority = ThreadPriority.Normal; Assert.Equal(ThreadPriority.Normal, t.Priority); e.Set(); waitForThread(); }
public static void NameTest() { string name = Guid.NewGuid().ToString("N"); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { var ct = Thread.CurrentThread; Assert.Equal(name, ct.Name); Assert.Throws <InvalidOperationException>(() => ct.Name = null); Assert.Throws <InvalidOperationException>(() => ct.Name = name + "b"); Assert.Equal(name, ct.Name); }); t.IsBackground = true; Assert.Null(t.Name); t.Name = null; t.Name = null; Assert.Null(t.Name); t.Name = name; Assert.Equal(name, t.Name); Assert.Throws <InvalidOperationException>(() => t.Name = null); Assert.Throws <InvalidOperationException>(() => t.Name = name + "b"); Assert.Equal(name, t.Name); t.Start(); waitForThread(); ThreadTestHelpers.RunTestInBackgroundThread(() => { var ct = Thread.CurrentThread; Assert.Null(ct.Name); ct.Name = null; ct.Name = null; Assert.Null(ct.Name); ct.Name = name; Assert.Equal(name, ct.Name); Assert.Throws <InvalidOperationException>(() => ct.Name = null); Assert.Throws <InvalidOperationException>(() => ct.Name = name + "b"); Assert.Equal(name, ct.Name); }); }
public static void InterruptInFinallyBlockTest_SkipOnDesktopFramework() { // A wait in a finally block can be interrupted. The desktop framework applies the same rules as thread abort, and // does not allow thread interrupt in a finally block. There is nothing special about thread interrupt that requires // not allowing it in finally blocks, so this behavior has changed in .NET Core. var continueThread = new AutoResetEvent(false); Action waitForThread; Thread t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { try { } finally { Assert.Throws <ThreadInterruptedException>(() => continueThread.CheckedWait()); } }); t.IsBackground = true; t.Start(); t.Interrupt(); waitForThread(); }
public static void ThreadStateTest() { var e0 = new ManualResetEvent(false); var e1 = new AutoResetEvent(false); Action waitForThread; var t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { e0.CheckedWait(); ThreadTestHelpers.WaitForConditionWithoutBlocking(() => e1.WaitOne(0)); }); Assert.Equal(ThreadState.Unstarted, t.ThreadState); t.IsBackground = true; Assert.Equal(ThreadState.Unstarted | ThreadState.Background, t.ThreadState); t.Start(); ThreadTestHelpers.WaitForCondition(() => t.ThreadState == (ThreadState.WaitSleepJoin | ThreadState.Background)); e0.Set(); ThreadTestHelpers.WaitForCondition(() => t.ThreadState == (ThreadState.Running | ThreadState.Background)); e1.Set(); waitForThread(); Assert.Equal(ThreadState.Stopped, t.ThreadState); t = ThreadTestHelpers.CreateGuardedThread( out waitForThread, () => ThreadTestHelpers.WaitForConditionWithoutBlocking(() => e1.WaitOne(0))); t.Start(); ThreadTestHelpers.WaitForCondition(() => t.ThreadState == ThreadState.Running); e1.Set(); waitForThread(); Assert.Equal(ThreadState.Stopped, t.ThreadState); }
private static void VerifyLocalDataSlot(LocalDataStoreSlot slot) { Assert.NotNull(slot); var waitForThreadArray = new Action[2]; var threadArray = new Thread[2]; var barrier = new Barrier(threadArray.Length); var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; Func <bool> barrierSignalAndWait = () => { try { Assert.True(barrier.SignalAndWait(UnexpectedTimeoutMilliseconds, cancellationToken)); } catch (OperationCanceledException) { return(false); } return(true); }; Action <int> threadMain = threadIndex => { try { Assert.Null(Thread.GetData(slot)); if (!barrierSignalAndWait()) { return; } if (threadIndex == 0) { Thread.SetData(slot, threadIndex); } if (!barrierSignalAndWait()) { return; } if (threadIndex == 0) { Assert.Equal(threadIndex, Thread.GetData(slot)); } else { Assert.Null(Thread.GetData(slot)); } if (!barrierSignalAndWait()) { return; } if (threadIndex != 0) { Thread.SetData(slot, threadIndex); } if (!barrierSignalAndWait()) { return; } Assert.Equal(threadIndex, Thread.GetData(slot)); if (!barrierSignalAndWait()) { return; } } catch (Exception ex) { cancellationTokenSource.Cancel(); throw new TargetInvocationException(ex); } }; for (int i = 0; i < threadArray.Length; ++i) { threadArray[i] = ThreadTestHelpers.CreateGuardedThread(out waitForThreadArray[i], () => threadMain(i)); threadArray[i].IsBackground = true; threadArray[i].Start(); } foreach (var waitForThread in waitForThreadArray) { waitForThread(); } }
public static void CountTest() { RemoteExecutor.Invoke(() => { const int TimersPerThread = 64; int processorCount = Environment.ProcessorCount; int totalTimerCount = processorCount * TimersPerThread; var timers = new List <Timer>(totalTimerCount); TimerCallback timerCallback = _ => { }; var startCreateTimerThreads = new ManualResetEvent(false); Action createTimerThreadStart = () => { startCreateTimerThreads.WaitOne(); for (int i = 0; i < TimersPerThread; ++i) { lock (timers) { timers.Add( new Timer( timerCallback, null, ThreadTestHelpers.UnexpectedTimeoutMilliseconds, ThreadTestHelpers.UnexpectedTimeoutMilliseconds)); Assert.True(Timer.ActiveCount >= timers.Count); } } }; var waitsForThread = new Action[processorCount]; for (int i = 0; i < processorCount; ++i) { Thread t = ThreadTestHelpers.CreateGuardedThread(out waitsForThread[i], createTimerThreadStart); t.IsBackground = true; t.Start(); } startCreateTimerThreads.Set(); foreach (Action waitForThread in waitsForThread) { waitForThread(); } // To leave some room for unknown timers to be scheduled and removed, remove a large number of timers at a time and // verify that the timer count has decreased while (timers.Count > 0) { long timerCountBeforeRemove = Timer.ActiveCount; int endIndex = timers.Count - processorCount * 8; for (int i = timers.Count - 1; i >= Math.Max(0, endIndex); --i) { timers[i].Dispose(); timers.RemoveAt(i); } if (endIndex >= 0) { Assert.True(Timer.ActiveCount < timerCountBeforeRemove); } } }).Dispose(); }