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(); } } }
/// <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); }
/// <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)); }