Beispiel #1
0
        private void ProcessTasks()
        {
            while (!_token.IsCancellationRequested)
            {
                var task = FindNextTask();

                DateTime nextTime = task == null?DateTime.Now.AddMinutes(1) : task.Timeout;

                var now = DateTime.Now;

                if (nextTime <= now)
                {
                    task.IncreaseCount();

                    _threadPool.Run(task.Action, task);

                    RemoveOldTasks();
                    task.GenerateNextTime(false);
                }
                else
                {
                    if ((int)(nextTime - now).TotalMilliseconds < 0)
                    {
                        _event.WaitOne(int.MaxValue);
                    }
                    else
                    {
                        _event.WaitOne(nextTime - now);
                    }

                    _event.Reset();
                }
            }
        }
Beispiel #2
0
        //=============================


        private void RunSimpleProcessWorkTest(int minThreadCount, int maxThreadCount, int queueCapacity, int workCount = 100000)
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(minThreadCount, maxThreadCount, queueCapacity, "name"))
            {
                Assert.IsTrue(testInst.ThreadCount >= minThreadCount);
                Assert.IsTrue(testInst.ActiveThreadCount >= minThreadCount);
                Assert.AreEqual(queueCapacity, testInst.QueueCapacity);
                Assert.IsTrue(testInst.IsWork);

                int expectedWork = workCount;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(true, true, true);

                Assert.AreEqual(0, testInst.ThreadCount);
                Assert.IsFalse(testInst.IsWork);
                Assert.AreEqual(expectedWork, executedWork);

                testInst.CompleteAdding();
            }
        }
Beispiel #3
0
        public void TestLongProcessWork()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 100, "name"))
            {
                Assert.AreEqual(100, testInst.QueueCapacity);

                int expectedWork = 100;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(250);
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(true, true, true);

                Assert.AreEqual(0, testInst.ThreadCount);
                Assert.AreEqual(0, testInst.ActiveThreadCount);
                Assert.IsFalse(testInst.IsWork);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
Beispiel #4
0
        public void WaitUntilStopWorkCorrect()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name"))
            {
                Assert.AreEqual(-1, testInst.QueueCapacity);

                int expectedWork = 100;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(200);
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(false, true, false);
                Assert.IsTrue(executedWork < expectedWork);
                Assert.IsTrue(testInst.State == ThreadPoolState.StopRequested);

                testInst.WaitUntilStop();
                Assert.IsTrue(testInst.State == ThreadPoolState.Stopped);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
Beispiel #5
0
        public void TestAwaitThroughSyncContext()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, 2 * Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                bool isNotFailed  = false;
                bool isThreadPool = false;

                testInst.Run(() =>
                {
                    var task = AwaitThroughSyncContext();
                    task.ContinueWith(t =>
                    {
                        Volatile.Write(ref isNotFailed, !t.IsFaulted);
                        Volatile.Write(ref isThreadPool, testInst.IsThreadPoolThread);
                    }, TaskContinuationOptions.ExecuteSynchronously).Wait();
                });

                testInst.Dispose(true, true, false);

                Assert.IsTrue(isNotFailed, "isNotFailed");
                Assert.IsTrue(isThreadPool, "isThreadPool");
            }
        }
Beispiel #6
0
        public static void RunThreads(Action work)
        {
            var _settings_pool = new DynamicThreadPoolOptions().UseOwnTaskScheduler;
            var _threadPool    = new DynamicThreadPool(1, 1, "threads");

            for (var i = 0; i < 1; i++)
            {
                _threadPool.Run(work);
                // Thread.Sleep(100000);
            }
        }
Beispiel #7
0
        public void TestCantAddAfterCompleteAdding()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name"))
            {
                Assert.IsTrue(testInst.TryRun(() => { }));

                testInst.CompleteAdding();

                Assert.IsFalse(testInst.TryRun(() => { }));

                testInst.Run(() => { });
            }
        }
Beispiel #8
0
        public void TestTaskSchedulerSetted()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                AtomicBool isPropperSceduller = new AtomicBool(false);

                testInst.Run(() =>
                {
                    isPropperSceduller.Value = TaskScheduler.Current == testInst.TaskScheduler;
                });

                TimingAssert.IsTrue(10000, isPropperSceduller, "isPropperSceduller");
                testInst.Dispose(true, true, false);
            }
        }
Beispiel #9
0
        public void TestQueueCapacityBoundExtends()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 10, "name"))
            {
                int expectedWork = 25 + Environment.ProcessorCount;
                int executedWork = 0;

                ManualResetEventSlim tracker = new ManualResetEventSlim();

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        tracker.Wait();
                        Interlocked.Increment(ref executedWork);
                    });
                }

                tracker.Set();

                testInst.Dispose(true, true, true);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
Beispiel #10
0
        public void TestNoSyncContextAndTaskSchedullerWhenNotConfigurated()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = false, UseOwnSyncContext = false
            }))
            {
                var defSyncContext    = SynchronizationContext.Current;
                var defTaskScheduller = TaskScheduler.Current;

                AtomicBool isDefaultSyncContext    = new AtomicBool(false);
                AtomicBool isDefaultTaskScheduller = new AtomicBool(false);

                testInst.Run(() =>
                {
                    isDefaultSyncContext.Value    = SynchronizationContext.Current == defSyncContext;
                    isDefaultTaskScheduller.Value = TaskScheduler.Current == defTaskScheduller;
                });

                TimingAssert.IsTrue(10000, isDefaultSyncContext, "isDefaultSyncContext");
                TimingAssert.IsTrue(10000, isDefaultTaskScheduller, "isDefaultTaskScheduller");
                testInst.Dispose(true, true, false);
            }
        }
Beispiel #11
0
        public void TestSyncContextSetted()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                AtomicBool isPropperSyncContext = new AtomicBool(false);

                testInst.Run(() =>
                {
                    if (SynchronizationContext.Current != null)
                    {
                        SynchronizationContext.Current.Post((st) =>
                        {
                            isPropperSyncContext.Value = testInst.IsThreadPoolThread;
                        }, null);
                    }
                });

                TimingAssert.IsTrue(10000, isPropperSyncContext, "isPropperSyncContext");
                testInst.Dispose(true, true, false);
            }
        }
Beispiel #12
0
        public void DynamicThreadPoolPerformBalancing()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, 4 * Environment.ProcessorCount, 1000, "name"))
            {
                Assert.AreEqual(0, testInst.ActiveThreadCount);

                // ========== Проверяем, что число потоков увеличивается автоматически от нуля ===========

                int executedTaskCount = 0;

                for (int i = 0; i < 1000; i++)
                {
                    testInst.Run(() =>
                    {
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }

                TimingAssert.AreEqual(5000, 1000, () => Volatile.Read(ref executedTaskCount));
                Assert.IsTrue(testInst.ActiveThreadCount > 0, "1. testInst.ActiveThreadCount > 0");

                // ======== Проверяем, что на большом числе задач он рано или поздно дойдёт до числа потоков равного числу ядер ===========

                executedTaskCount = 0;
                for (int i = 0; i < testInst.MaxThreadCount * testInst.QueueCapacity; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(1);
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }


                TimingAssert.AreEqual(15000, testInst.MaxThreadCount * testInst.QueueCapacity, () => Volatile.Read(ref executedTaskCount));
                Assert.IsTrue(testInst.ActiveThreadCount >= Environment.ProcessorCount, "2. testInst.ActiveThreadCount >= Environment.ProcessorCount");


                // ======== Проверяем, что на долгих задачах число потоков может стать больше числа ядер ===========

                executedTaskCount = 0;
                for (int i = 0; i < 1000; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(20);
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }


                TimingAssert.IsTrue(30000, () => Volatile.Read(ref executedTaskCount) >= 500);

                Assert.IsTrue(testInst.ActiveThreadCount > Environment.ProcessorCount, "3. testInst.ActiveThreadCount > Environment.ProcessorCount");
                Assert.IsTrue(testInst.ActiveThreadCount <= testInst.MaxThreadCount, "3. testInst.ActiveThreadCount <= testInst.MaxThreadCount");

                TimingAssert.AreEqual(30000, 1000, () => Volatile.Read(ref executedTaskCount));

                TimingAssert.IsTrue(5000, () => testInst.ActiveThreadCount <= Environment.ProcessorCount, "4. testInst.ActiveThreadCount <= Environment.ProcessorCount");
            }
        }
Beispiel #13
0
        private void RunTestOnPool(DynamicThreadPool pool, int totalTaskCount, int taskSpinCount, int spawnThreadCount, int spawnSpinTime, bool spawnFromPool)
        {
            Random rndGenerator = new Random();

            int executedTaskCounter = 0;
            int completedTaskCount  = 0;


            Action taskAction = null;

            taskAction = () =>
            {
                int curTaskSpinCount = taskSpinCount;
                lock (rndGenerator)
                    curTaskSpinCount = rndGenerator.Next(taskSpinCount);

                Thread.SpinWait(curTaskSpinCount);

                if (spawnFromPool)
                {
                    if (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                    {
                        pool.Run(taskAction);
                    }
                }

                Interlocked.Increment(ref completedTaskCount);
            };

            Barrier bar = new Barrier(spawnThreadCount + 1);

            Random spawnRndGenerator = new Random();

            Thread[]    spawnThreads = new Thread[spawnThreadCount];
            ThreadStart spawnAction  = () =>
            {
                bar.SignalAndWait();
                while (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                {
                    pool.Run(taskAction);

                    int curSpawnSpinCount = spawnSpinTime;
                    lock (spawnRndGenerator)
                        curSpawnSpinCount = spawnRndGenerator.Next(spawnSpinTime);

                    Thread.SpinWait(curSpawnSpinCount);
                }
            };


            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i] = new Thread(spawnAction);
            }

            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i].Start();
            }

            bar.SignalAndWait();

            TimingAssert.AreEqual(60 * 1000, totalTaskCount, () => Volatile.Read(ref completedTaskCount));
        }
Beispiel #14
0
        public void Run(SearchTask sTask, Action action)
        {
            _threadPool.Run(action);

            _tasks.Add(sTask);
        }