public STAContext()
 {
     _queue = new BlockingCollection <Task>();
     _synchronizationContext = new STASynchronizationContext(this);
     _taskScheduler          = new STATaskScheduler(this);
     TaskFactory             = new TaskFactory(CancellationToken.None, TaskCreationOptions.HideScheduler, TaskContinuationOptions.HideScheduler, _taskScheduler);
 }
        public void Scheduler_WhenThreadRunsTask_ShouldUpdateLastUsed()
        {
            const int IDLE_TIMEOUT        = 10;
            var       idleTrigger         = new StubIdleTrigger(IDLE_TIMEOUT);
            int       numThreadsAfterIdle = -1;
            var       evt = new ManualResetEventSlim();

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
                Task t1 = new Task(() =>
                {
                });

                t1.Start(scheduler);

                Thread.Sleep(2 * IDLE_TIMEOUT);

                Task t2 = new Task(() =>
                {
                });

                t2.Start(scheduler);

                t2.Wait();

                idleTrigger.FireCheckIdle();

                numThreadsAfterIdle = scheduler.GetThreadCount();

                evt.Set();
            }

            Assert.AreEqual(1, numThreadsAfterIdle);
        }
        public void Scheduler_WhenThreadNotIdleForTimeout_ShouldNotThreadFromPool()
        {
            var idleTrigger          = new StubIdleTrigger(10000);
            int numThreadsBeforeIdle = -1;
            int numThreadsAfterIdle  = -1;
            var evt = new ManualResetEventSlim();

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
                Task t = new Task(() =>
                {
                    evt.Wait();
                });

                t.Start(scheduler);

                numThreadsBeforeIdle = scheduler.GetThreadCount();

                idleTrigger.FireCheckIdle();

                numThreadsAfterIdle = scheduler.GetThreadCount();

                evt.Set();
            }

            Assert.AreEqual(1, numThreadsBeforeIdle);
            Assert.AreEqual(1, numThreadsAfterIdle);
        }
        public void Scheduler_WhenThreadIdleForTimeout_ShouldRemoveThreadFromPool()
        {
            var idleTrigger          = new StubIdleTrigger(0);
            int numThreadsBeforeIdle = -1;
            int numThreadsAfterIdle  = -1;

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
                Task t = new Task(() =>
                {
                });

                t.Start(scheduler);

                t.Wait();

                numThreadsBeforeIdle = scheduler.GetThreadCount();

                idleTrigger.FireCheckIdle();

                numThreadsAfterIdle = scheduler.GetThreadCount();
            }

            Assert.AreEqual(1, numThreadsBeforeIdle);
            Assert.AreEqual(0, numThreadsAfterIdle);
        }
        public void QueueTask_WhenQueuesFirstTask_ShouldExecuteTaskOnSTAThread()
        {
            using (var scheduler = new STATaskScheduler(1, new StubIdleTrigger()))
            {
                ApartmentState apartment = ApartmentState.MTA;
                var            evt       = new ManualResetEventSlim();

                Task t = new Task(() =>
                {
                    apartment = Thread.CurrentThread.GetApartmentState();
                    evt.Set();
                });

                t.Start(scheduler);

                if (evt.Wait(1000))
                {
                    Assert.AreEqual(ApartmentState.STA, apartment);
                }
                else
                {
                    Assert.Fail();
                }
            }
        }
示例#6
0
文件: Task.cs 项目: wey12138/Wave
        /// <summary>
        ///     Executes all of the items in the collection on individual threads and waits for all of the actions (that are issued
        ///     as a background process on a <see cref="BackgroundWorker" /> thread)
        ///     to complete.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items">The items that will be used as the parameter to the task.</param>
        /// <param name="task">The task.</param>
        /// <param name="degreeOfParallelism">The degree of parallelism.</param>
        public static void Parallel <T>(IEnumerable <T> items, Action <T> task, int degreeOfParallelism)
        {
            var scheduler = new STATaskScheduler(degreeOfParallelism);
            var tasks     = new List <Threading.Tasks.Task>();

            using (var throttler = new SemaphoreSlim(degreeOfParallelism))
            {
                var semaphore = throttler;

                foreach (var element in items)
                {
                    throttler.Wait();

                    var thread = Threading.Tasks.Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            task(element);
                        }
                        finally
                        {
                            semaphore.Release();
                        }
                    }, CancellationToken.None, TaskCreationOptions.None, scheduler);

                    tasks.Add(thread);
                }

                Threading.Tasks.Task.WaitAll(tasks.ToArray());
            }
        }
        public void Dispose_WhenCalled_ShouldDisposeIdleTrigger()
        {
            var idleTrigger = new StubIdleTrigger();

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
            }

            Assert.IsTrue(idleTrigger.Disposed);
        }
        public void Ctor_WhenPassedAnIdleTrigger_ShouldSubscribeToCheckIdleEvent()
        {
            var  idleTrigger = new StubIdleTrigger();
            bool subscribed  = false;

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
                subscribed = idleTrigger.FireCheckIdle();
            }

            Assert.IsTrue(subscribed);
        }
        public void IdleTrigger_WhenFired_ShouldCheckIdleTimeoutEveryTime()
        {
            var idleTrigger = new StubIdleTrigger();
            int checkCount  = 0;

            using (var scheduler = new STATaskScheduler(1, idleTrigger))
            {
                idleTrigger.FireCheckIdle();
                idleTrigger.FireCheckIdle();
                checkCount = idleTrigger.IdleTimeoutCheckCount;
            }

            Assert.AreEqual(2, checkCount);
        }
        public void QueueTask_WhenQueuesTaskAndThreadAvailable_ShouldRunTasks()
        {
            using (var scheduler = new STATaskScheduler(2, new StubIdleTrigger()))
            {
                int maxConcurrency     = 0;
                int currentConcurrency = 0;
                var evt              = new ManualResetEventSlim();
                var countdownDone    = new CountdownEvent(2);
                var incrementDoneEvt = new CountdownEvent(2);

                Task t = new Task(() =>
                {
                    maxConcurrency = Interlocked.Increment(ref currentConcurrency);
                    incrementDoneEvt.Signal();
                    evt.Wait();
                    Interlocked.Decrement(ref currentConcurrency);
                    countdownDone.Signal();
                });
                Task t2 = new Task(() =>
                {
                    maxConcurrency = Interlocked.Increment(ref currentConcurrency);
                    incrementDoneEvt.Signal();
                    evt.Wait();
                    Interlocked.Decrement(ref currentConcurrency);
                    countdownDone.Signal();
                });

                t.Start(scheduler);
                t2.Start(scheduler);

                if (incrementDoneEvt.Wait(1000))
                {
                    evt.Set();
                }
                else
                {
                    Assert.Fail();
                }

                if (countdownDone.Wait(1000))
                {
                    Assert.AreEqual(2, maxConcurrency);
                }
                else
                {
                    Assert.Fail();
                }
            }
        }
        public void TryExecuteTaskInline_WhenTriggeredFromNonSTAThread_ShouldNotExecuteTask()
        {
            var evt             = new ManualResetEventSlim();
            var notInlinedEvent = new ManualResetEventSlim();
            int callingThread   = -1;
            int executionThread = -1;

            using (var scheduler = new STATaskScheduler(1))
            {
                scheduler.TaskNotInlined += (s, e) =>
                {
                    notInlinedEvent.Set();
                };

                var t1 = new Task(() =>
                {
                    evt.Wait();
                });

                var t2 = new Task(() =>
                {
                    executionThread = Thread.CurrentThread.ManagedThreadId;
                });

                t1.Start(scheduler);
                t2.Start(scheduler);

                var staThread = new Thread(() =>
                {
                    callingThread = Thread.CurrentThread.ManagedThreadId;
                    t2.Wait();
                });
                staThread.SetApartmentState(ApartmentState.MTA);
                staThread.IsBackground = true;
                staThread.Start();

                notInlinedEvent.Wait();

                evt.Set();

                t2.Wait();
            }

            Assert.AreNotEqual(callingThread, executionThread);
        }
        public void TryDequeue_WhenTaskCancelled_ShouldPreventTaskFromRunning()
        {
            var  evt                     = new ManualResetEventSlim();
            bool t2Executed              = false;
            int  numExceptions           = 0;
            bool cancelledExceptionFound = false;

            using (var scheduler = new STATaskScheduler(1))
            {
                var t1 = new Task(() =>
                {
                    evt.Wait();
                });

                var cts = new CancellationTokenSource();

                var t2 = new Task(() =>
                {
                    t2Executed = true;
                }, cts.Token);

                t1.Start(scheduler);
                t2.Start(scheduler);

                cts.Cancel();

                evt.Set();
                try
                {
                    t2.Wait();
                }
                catch (AggregateException x)
                {
                    numExceptions = x.InnerExceptions.Count;
                    if (numExceptions > 0 && x.InnerExceptions.First().GetType() == typeof(TaskCanceledException))
                    {
                        cancelledExceptionFound = true;
                    }
                }
            }

            Assert.IsFalse(t2Executed);
            Assert.AreEqual(1, numExceptions);
            Assert.IsTrue(cancelledExceptionFound);
        }
        public void TryExecuteTaskInline_WhenTriggeredFromSTAThread_ShouldExecuteTask()
        {
            var evt             = new ManualResetEventSlim();
            int callingThread   = -1;
            int executingThread = -2;

            using (var scheduler = new STATaskScheduler(1))
            {
                var t1 = new Task(() =>
                {
                    evt.Wait();
                });

                var t2 = new Task(() =>
                {
                    executingThread = Thread.CurrentThread.ManagedThreadId;
                });

                t1.Start(scheduler);
                t2.Start(scheduler);

                var staThread = new Thread(() =>
                {
                    callingThread = Thread.CurrentThread.ManagedThreadId;
                    t2.Wait();
                });
                staThread.SetApartmentState(ApartmentState.STA);
                staThread.Start();

                staThread.Join();

                evt.Set();
            }

            Assert.AreEqual(callingThread, executingThread);
        }
示例#14
0
文件: Task.cs 项目: wey12138/Wave
        /// <summary>
        ///     Runs the background process as a <see cref="Threading.Tasks.Task" /> thread using the specified arguments that are
        ///     passed to the methods.
        /// </summary>
        /// <param name="task">The delegate that handles the execution on the work.</param>
        public static Threading.Tasks.Task Schedule(Action task)
        {
            var scheduler = new STATaskScheduler(1);

            return(Threading.Tasks.Task.Factory.StartNew(task, CancellationToken.None, TaskCreationOptions.None, scheduler));
        }