public void Sched_Task_SubTaskExecutionSequencing()
        {
            UnitTestSchedulingContext rootContext = new UnitTestSchedulingContext();
            OrleansTaskScheduler scheduler = TestInternalHelper.InitializeSchedulerForTesting(rootContext);

            UnitTestSchedulingContext context = new UnitTestSchedulingContext();
            scheduler.RegisterWorkContext(context);

            LogContext("Main-task " + Task.CurrentId);

            int n = 0;

            Action closure = () =>
            {
                LogContext("ClosureWorkItem-task " + Task.CurrentId);

                for (int i = 0; i < 10; i++)
                {
                    int id = -1;
                    Action action = () =>
                    {
                        id = Task.CurrentId.HasValue ? (int)Task.CurrentId : -1;

                        // ReSharper disable AccessToModifiedClosure
                        LogContext("Sub-task " + id + " n=" + n);

                        int k = n;
                        output.WriteLine("Sub-task " + id + " sleeping");
                        Thread.Sleep(100);
                        output.WriteLine("Sub-task " + id + " awake");
                        n = k + 1;
                        // ReSharper restore AccessToModifiedClosure
                    };
                    Task.Factory.StartNew(action).ContinueWith(tsk =>
                    {
                        LogContext("Sub-task " + id + "-ContinueWith");

                        output.WriteLine("Sub-task " + id + " Done");
                    });
                }
            };

            IWorkItem workItem = new ClosureWorkItem(closure);

            scheduler.QueueWorkItem(workItem, context);

            // Pause to let things run
            output.WriteLine("Main-task sleeping");
            Thread.Sleep(TimeSpan.FromSeconds(2));
            output.WriteLine("Main-task awake");

            // N should be 10, because all tasks should execute serially
            Assert.True(n != 0, "Work items did not get executed");
            Assert.Equal(10, n);  // "Work items executed concurrently"
            scheduler.Stop();
        }
        public void Sched_SimpleFifoTest()
        {
            // This is not a great test because there's a 50/50 shot that it will work even if the scheduling
            // is completely and thoroughly broken and both closures are executed "simultaneously"
            UnitTestSchedulingContext context = new UnitTestSchedulingContext();
            OrleansTaskScheduler orleansTaskScheduler = TestInternalHelper.InitializeSchedulerForTesting(context);
            ActivationTaskScheduler scheduler = orleansTaskScheduler.GetWorkItemGroup(context).TaskRunner;

            int n = 0;
            // ReSharper disable AccessToModifiedClosure
            IWorkItem item1 = new ClosureWorkItem(() => { n = n + 5; });
            IWorkItem item2 = new ClosureWorkItem(() => { n = n * 3; });
            // ReSharper restore AccessToModifiedClosure
            orleansTaskScheduler.QueueWorkItem(item1, context);
            orleansTaskScheduler.QueueWorkItem(item2, context);

            // Pause to let things run
            Thread.Sleep(1000);

            // N should be 15, because the two tasks should execute in order
            Assert.True(n != 0, "Work items did not get executed");
            Assert.Equal(15, n);
            output.WriteLine("Test executed OK.");
            orleansTaskScheduler.Stop();
        }
        public void Sched_Task_ClosureWorkItem_Wait()
        {
            UnitTestSchedulingContext cntx = new UnitTestSchedulingContext();
            OrleansTaskScheduler scheduler = TestInternalHelper.InitializeSchedulerForTesting(cntx);

            const int NumTasks = 10;

            ManualResetEvent[] flags = new ManualResetEvent[NumTasks];
            for (int i = 0; i < NumTasks; i++)
            {
                flags[i] = new ManualResetEvent(false);
            }

            Task[] tasks = new Task[NumTasks];
            for (int i = 0; i < NumTasks; i++)
            {
                int taskNum = i; // Capture
                tasks[i] = new Task(() => { output.WriteLine("Inside Task-" + taskNum); flags[taskNum].WaitOne(); });
            }

            ClosureWorkItem[] workItems = new ClosureWorkItem[NumTasks];
            for (int i = 0; i < NumTasks; i++)
            {
                int taskNum = i; // Capture
                workItems[i] = new ClosureWorkItem(() =>
                {
                    output.WriteLine("Inside ClosureWorkItem-" + taskNum);
                    tasks[taskNum].Start(scheduler);
                    bool ok = tasks[taskNum].Wait(TimeSpan.FromMilliseconds(NumTasks * 100));
                    Assert.True(ok, "Wait completed successfully inside ClosureWorkItem-" + taskNum);
                });
            }

            foreach (var workItem in workItems) scheduler.QueueWorkItem(workItem, cntx);
            foreach (var flag in flags) flag.Set();
            for (int i = 0; i < tasks.Length; i++)
            {
                bool ok = tasks[i].Wait(TimeSpan.FromMilliseconds(NumTasks * 150));
                Assert.True(ok, "Wait completed successfully for Task-" + i);
            }


            for (int i = 0; i < tasks.Length; i++)
            {
                Assert.False(tasks[i].IsFaulted, "Task.IsFaulted-" + i + " Exception=" + tasks[i].Exception);
                Assert.True(tasks[i].IsCompleted, "Task.IsCompleted-" + i);
            }
        }