Shafqat's Recent Online Activity

Twitter

November 18, 2007

Spider's Web: Spawning threads in .NET (Part 1 of 5), The Basics

Now with our multi core CPUs and high expectations of application responsiveness, executing the application in multiple paths have become a requirement rather than an option. Also running the code in application servers requires that we know a thing or two about threads. So I have decided to write a few posts about threads and their use in .NET environment. This is the first part of a five part series post.

History

A process in traditional programming languages pursued one execution path. Unix platform provided the fork command which would enable one to split the execution into different paths. A spawned process could have independent execution path but that required quite an amount of resources. A thread is a simpler and cheaper way of having different execution path at real time with the benefit shared memory space. Each process has a minimum of one thread. With the invention of threads, the code blocks of a same process could run virtually simultaneously. With today's multi core CPUs the 'virtually' part of running simultaneously can be taken out and a thread can in physical world run simultaneously. The implementations of threads are different on different operating systems. For more historical information on threads please refer to the Wikipedia Article.

The Basics

System.Threading namespace contains the classes required for threading. This is the basic syntax of spawning a thread.

If we observe the output then we can see that both execution path are running at the same time. Several points to note here.

There is no time deterministic way of scheduling code executing in a thread. When there are multiple threads the OS will decide which time slice to give which thread and when. Also the time slices are not equal.

After calling a thread start from another thread the call will return control immediately that other thread will start at its own time which can be immediate or later

Waiting using Thread.Sleep()

Thread.Sleep() is a static function which causes the executing thread to pause for specified number of milliseconds. It it quite useful when you need to pause processing for a while. It must be noted that Thread.Sleep() will only pause the executing thread which called the Sleep function.

Wait for a Thread to finish by using thread.Join()

Join() is an instance function available to a thread. This blocks the calling thread until the target thread has finished.

This code sample demonstrates the use of static function Thread.Sleep() and instance function Join(). The application started a thread waits for thread to finish by calling thread1.Join(). The function CountSlowly waits 1000 ms before counting each number by putting the thread1 to sleep. The application output looks like this ...

Passing parameters to the thread function

Before .NET 2.0 the function passed to the thread had to be a void function without any parameter. The basic idea was to pass the parameters to object via private variable. However that creates a problem for static functions or instances of objects stored in static variables, which I will discuss in a later part. So we can modify our WorkerObject class to store a parameter. The code should look like this

This way we are keeping the function signature same while passing the parameter to the object. This is a dangerous practice if the object instance is being shared among different threads at the same time, otherwise it is harmless. From .NET 2.0 we have a new feature of passing parameters. In order to pass parameters we need to use ParameterizedThreadStart() delegate to pass parameters to a thread function. The signature of the function should look like this

voidfunction (object)

Now only one parameter can be passed to the function. So if we need to pass multiple parameters then we will need to create a custom object that holds the parameters or we can use a dictionary. Also inside the function we need unwrap the object to a strong type and work with it. In the next example we are going to pass two parameters to the function.

As we can see that we need pass two parameters to the function name and how many times will we count, so we have created a class to hold multiple parameters called CountParams. Then inside the function we unwrap the object to our parameter class and use it. Please note the if we had only one parameter to pass to the function like and integer then we would not need to create this parameter class and would be able to directly cast the object to int. Lets observe how we are calling the function ...

Now the above example shows us that we construct the thread with a ParameterizedThreadStart delegate and then in thread.Start() function we are passing our custom parameter object.

There is something called Thread Local Storage (TLS) which I will cover in a future part in the thread post series.

Multicasting

One more thing to remember that the delegate for ThreadStart is a like normal multicast delegate. So we can assign more than one function to the delegate. But that will not call each of the functions simultaneously rather call them on the same thread one by one. The example below shows sample multicasting ...