CCR 101 - Part 2: DispatcherQueues and Tasks

Let's just get straight into some samples, as a means of introducing some of the CCR types and concepts. To run these samples yourself, you'll need the .NET 2.0 Framework SDK, and the MSRS 1.5 release. Unless otherwise stated, all the samples are just simple console applications that reference Ccr.Core.dll.

Here is the canonical example:

class Sample01 {
static void Main(string[] args) {
using (DispatcherQueue dq = new DispatcherQueue()) {
dq.Enqueue(new Task(delegate() {
Console.WriteLine("Hello world.");
}));
Console.ReadLine();
}
}
}

Nothing spectacular here, and frankly nothing that couldn't be achieved with ThreadPool.QueueUserWorkItem. It does, however, introduce the DispatcherQueue. Instances of this type are really just queues of delegates waiting to be executed. These delegates are removed in turn from the queue and executed over the available threads (more on that soon), so in the presence of multiple threads, might execute out of order. For example this code, which enqueues 10 items...

class Sample02 {
static void Main(string[] args) {
using (DispatcherQueue dq = new DispatcherQueue()) {
for (int i = 0; i < 10; ++i) {
int num = i;
dq.Enqueue(new Task(delegate() {
Console.WriteLine("Hello world({0}).", num.ToString());
}));
}
Console.ReadLine();
}
}
}

...produces this result on my machine:


Hello world(0).
Hello world(1).
Hello world(2).
Hello world(3).
Hello world(4).
Hello world(5).
Hello world(6).
Hello world(7).
Hello world(9).
Hello world(8).


Again, this is exactly the same sort of behaviour you see over the CLR thread-pool.


Another type visible in both samples is the Task, which itself implements ITask, an interface that encapsulates the delegate and exposes an Execute method (no prizes for guessing what that does). DispatcherQueues are populated with ITasks, rather than the delegates directly. This indirection allows for more flexibility in terms of the types of tasks that can be queued. For example, there is a generic form of the Task class specialized by a single type, that invokes delegates that take an argument of that type. So we could rewrite Sample02 as:

class Sample03 {
static void Main(string[] args) {
using (DispatcherQueue dq = new DispatcherQueue()) {
for (int i = 0; i < 10; ++i) {
dq.Enqueue(new Task<int>(i, delegate(int val) {
Console.WriteLine("Hello world({0}).", val.ToString());
}));
}
Console.ReadLine();
}
}
}

There are many different types of tasks available in the CCR and we'll look at some of the more interesting ones in future posts. Often however, the higher-level abstractions of the CCR library do most of the task creation and queuing for us.


Just before we complete our initial look at DispatcherQueues, it's worth discussing two configurable properties that this type supports:



  1. Scheduling policy. The DispatcherQueues created for the samples so far run with 'unconstrained' policy. This means that there are no logical limits on the number or frequency of tasks that may be enqueued. It is possible to constrain this policy by controlling either the maximum number of items in the queue or the frequency with which they may be added. You can also decide whether a breach of these constraints results in the caller blocking or tasks being dropped.

  2. The target thread-pool. Creating a DispatcherQueue via the default constructor will cause tasks to be executed over the regular CLR thread-pool. You can however construct a DispatcherQueue with a reference to a custom thread-pool. These thread-pools are controlled by a Dispatcher, a type that is the focus of Part 3 and provides facilities missing from the CLR thread-pool.

And finally, note that the DispatcherQueue is disposable. If you are using DispatcherQueues without reference to a controlling Dispatcher, you don't strictly need to dispose of them, but this is an implementation detail you shouldn't rely on.


1 comments:

  1. This is very interesting. I was under the impression that CCR is running on a different Kernel than Window's (or possibly under the kernel). However, from what you are describing it is not.?

    B
    http://www.christian-science-practitioner.net

    on March 16, 2010 at 6:39 AM