Welcome to

Magenic Technologies Community Blog

Sign in | Join | Help

Dual-Threaded TaskManager on a Single Core

I just ran the following code on a single core machine:

static void Main(string[] args)
{
    Task Task1;
    Task Task2;
    Action<object> MainAction;
    TaskManagerPolicy CurrentPolicy;

    MainAction = ActionMethod;
    CurrentPolicy = new TaskManagerPolicy(2, 2);
    TaskManager CurrentTaskManager = new TaskManager(CurrentPolicy);
    Task1 = Task.Create(MainAction, CurrentTaskManager);
    Task2 = Task.Create(MainAction, CurrentTaskManager);
    Task1.Wait();
    Task2.Wait();
}

static void ActionMethod(object o)
{
    Console.WriteLine("Thread Name: {0}", Thread.CurrentThread.Name);
}

My intent with this code was to see the two tasks executing on separate threads. Since the default TaskManager uses one thread per processor, and since I was running the code on a single core machine, the default TaskManager would have executed both tasks on a single thread. In the code above, I used a TaskManagerPolicy object to specify a minimum of two threads and an ideal thread count of two, and I constructed a new TaskManager using that policy.

Imagine my surprise when the output was as follows:

Thread Name: Worker 1
Thread Name: Worker 1

Both tasks ran on the same thread! This wasn't what I was expecting, especially since I explicitly asked for two threads in my task manager policy object.

Then, I modified the ActionMethod to put the task to sleep:

static void ActionMethod(object o)
{
    Console.WriteLine("Thread Name: {0}", Thread.CurrentThread.Name);
    Thread.Sleep(5000);

}

Then, my output changed to what I was expecting:

Thread Name: Worker 1
Thread Name: Worker 2

What was the difference? The difference has to do with issues with threads and blocking.

When tasks are created, they are placed in a work queue that is managed by the associated TaskManager object. The TaskManager object also creates the requested two worker threads. Adding the tasks to the TaskManager object's work queue signals one of the worker threads that an item is available and the worker thread begins running the task. Since there is, in my situation, only one core, the TaskManager object has no way of notifying the second worker thread of the existence of Task2, until Task1 is finished or blocks. Without the call to Thread.Sleep(), as in my first example, Worker Thread 1 finishes Task1 and the TaskManager object signals Worker Thread 1 again to start Task2.

With the call to Thread.Sleep(), as in my second example, Worker Thread 1 blocks, and the operating system scheduler switches to a runable thread. The TaskManager object can now signal Worker Thread 2 to start Task2.

Published Monday, March 17, 2008 10:57 PM by jefff

Comments

No Comments

Anonymous comments are disabled