Monday, February 14, 2011

Threading Part - 2


This post is in continuation with Threading Part - 1....

In first post, we have seen the basic understanding on the Threading and its usage.
Now, let us consider comparatively complex scenarios....

Using Thread.Join
More often than not, you will need your application to wait for a thread to complete
execution. To accomplish this, the Thread class supports the Join method:

// C#
theThread.Join();

The Join method tells the system to make your application wait until the thread has
completed. Of course, in this simple case you do not really need a second thread
because you are just waiting for it to complete anyway. A better example is for us to
have five threads that all do some work and to wait for them. When we are working
with multiple threads, our programming task is a bit more complicated, as we need to
wait for all our threads. We can do this by keeping a reference to all our threads and calling Join on each of the threads to wait for the threads to complete, one at a time,as demonstrated in the following code:

// C#
ThreadStart operation = new ThreadStart(SomeWork);
Thread[] theThreads = new Thread[5];
for (i nt x = 0; x < 5; ++x)
{
// Creates, but does not start, a new thread
theThreads[x] = new Thread(operation);
// Starts the work on a new thread
theThreads[x].Start() ;
}
// Wai t for each thread to complete
foreach (Thread t in theThreads)
{
t.Join();
}
By storing the threads in an array, we can wait for each of the Threads one at a time. As each thread completes, the Join method will return and we can continue.

Thread Priority
The Thread class supports the setting or getting of the priority of a thread using the ThreadPriority enumeration.

  1. Highest - The highest priority
  2. AboveNormal - Higher priority than Normal
  3. Normal - The default priority
  4. BelowNormal - Lower than Normal
  5. Lowest - The lowest priority



Threads are scheduled based on this enumeration. In most cases, you will want to use
the default (Normal). Deciding to use threads that have lower thread priority can
cause the operation system to starve a thread more than you might expect, or if you
use higher priorities (especially Highest), you can starve the system. Although it is necessary to use non-Normal thread priorities at times, make this decision with much caution. Increasing the performance of a system simply by increasing thread priority is not likely to help in the long term, as other starved threads tend to back up and cause unexpected consequences.

Passing Data to Threads
In each of the earlier examples, we were using the ThreadStart delegate, which takes
no parameters. In most real-world use of threading, you will need to pass information
to individual threads. To do this, you need to use a new delegate called ParameterizedThreadStart. This delegate specifies a method signature with a single parameter of type Object and returns nothing. The following code snippet provides an example:

// C#
static void WorkWithParameter(object o)
{
string i nfo = (string) o;
for (int x = 0; x < 10; ++x)
{
Console. WriteLine("{0}: {1}", i nfo,
Thread.CurrentThread.ManagedThreadId);
// Slow down thread and let other threads work
Thread. Sleep(10);
}
}

This is a method that takes a single Object parameter (and therefore can be a reference to any object). To use this as the starting point of a thread call, you can create a ParameterizedThreadStart delegate to point at this new method and use the Thread.Start method’s overload that takes a single object parameter. The following code snippet provides an example:

// C#
ParameterizedThreadStart operation = new ParameterizedThreadStart(WorkWithParameter);
// Creates, but does not start, a new thread
Thread theThread = new Thread(operation);
// Starts the work on a new thread
theThread.Start("Hel l o");
// A Second Thread wi th a different parameter
Thread newThread = new Thread(operation);
newThread.Start("Goodbye");

Be aware that because the WorkWithParameter method takes an object, Thread. Start
could be called with any object instead of the string it expects. Being careful in choosing your starting method for a thread to deal with unknown types is crucial to good threading code. Instead of blindly casting the method parameter into our string, it is a better practice to test the type of the object, as shown in the following example:
// C#
string i nfo = o as string;
if (info == null )
{
throw Invali dProgramException("Parameter for thread must be a string");
}

No comments:

Post a Comment