示例#1
0
        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();
            }
        }
示例#2
0
        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));
        }
示例#3
0
        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());
        }
示例#4
0
        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();
        }
示例#5
0
        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();
        }
示例#6
0
    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();
        }
    }
示例#7
0
        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();
        }
示例#8
0
        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();
        }
示例#9
0
        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);
            });
        }
示例#10
0
        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();
        }
示例#11
0
        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);
        }
示例#12
0
        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();
            }
        }
示例#13
0
    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();
    }