LA.NET [EN]

May 28

As we’ve seen in the last post of the series, we can use the thread pool for scheduling several “types” of asynchronous operations and to amortize the penalty we pay when we need to create extra threads. In fact, I’d say that most operations should be performed by using a thread from the thread pool.

Today we’re going to look at one of the operations we can perform on thread pool: queuing work items. Interacting with the CLR managed thread pool can be accomplished through one of the several static methods of the ThreadPool class. For queing work items, we can use one of two methods: QueueUserWorkItem or UnsafeQueueUserWorkItem.

public static bool QueueUserWorkItem(WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callBack,
                                                                             object state);
public static bool UnsafeQueueUserWorkItem(WaitCallback callBack,
                                                                                 object state);

According to Joe Duffy’s excellent book, you should disregard the return value because failures will always be communicated through exceptions (I did check the docs and they don’t mention what false means :),,)

The main difference between the two is that the latest does not capture the ExecutionContext when you queue the work item (which means that it won’t also be used when the callback you pass is invoked). Both methods allow you to pass a reference to some object which will get passed to the callback when its processed.

Even though QueueUserWorkItem is more “secure” than the UnsafeQueueWorkItem (due to the fact that the context is captured and flowed – since the SecurityContext is part of the ExecutionContext, this means that you cannot elevate privileges by queuing work items on the thread pool), it’s also true that QueueUserWorkItem is slower than UnsafeQueueWorkItem (due to the overhead imposed by capturing and restoring the context).

When using a thread from the pool, it’s important to understand a few points:

  • you don’t control the thread that will invoke your callback;
  • the pool has only background threads. This means that they won’t keep a process running when the main thread exits. If you need to ensure that, then you need to create a thread by hand (ie, you need to use the Thread class);
  • Don’t forget the clean up before ending your work (especially if you’ve set cultures and other stuff). Even though these might get cleaned, there are some that won’t (ex.: TLS state – which, btw, you shouldn’t be using).

Enough talk…let’s see some code:

static void Main(string[] args) {
Console.WriteLine("Main thread Id: {0}",
             Thread.CurrentThread.ManagedThreadId);
  var evt = new ManualResetEvent(false);
  ThreadPool.QueueUserWorkItem( state => {
       Console.WriteLine("Thread Id: {0}",
                      Thread.CurrentThread.ManagedThreadId);
       Thread.Sleep(2000);
       Console.WriteLine("FInishing work");
       evt.Set();
     });
     evt.WaitOne();
     Console.WriteLine("Ending program");
}

The QueueUserWorkItem method expects a WaitCallback delegate which looks like this:

public delegate void WaitCallback(object state);

The state parameters will only contain a valid value when you use the overload which receives an object parameter. As you can see, the code is pretty similar to the one you had when we created threads “by hand”.

The most important detail of the previous code is synchronization! If we didn’t wait on the event, we wouldn’t really see much because the process would terminate before the secondary thread would have a chance to end (since pool’s threads are background threads, they don’t keep the process alive when all foreground threads have ended running).

And that’s it for today. Keep tuned for more on the thread pool.

3 comments so far

  1. viagra cialis better
    5:14 am - 8-2-2009

    EOAZfP Beautiful site!

  2. etene
    11:30 pm - 12-30-2009

    I”ve got an iphone 3G 16gb and something terrible happened to it. My phone fell of the toilet bowl and it doesn”t function anymore. My phone is still under warranty. I”m planning to bring it to the Genius bar to get it replaced. My question is how much do I have to pay to get it replaced. I live in Australia so I wanna know the price in AUD. Will the apple store replace my phone that has been damaged by water? or will they just fix it?

    ________________
    unlock iphone