Creating Threads Using Threadpool


So far, you have looked at creating and destroying threads by working with a single thread at a time using the Thread class. It is important to note that it is expensive (CPU intensive) to build up and destroy threads in this manner. For this reason, the CLR contains a built-in thread pool for you to use for your applications. This thread pool can be accessed via the ThreadPool class.

The ThreadPool class will work to reuse existing threads from a managed pool of threads and when it is done using the thread, the thread will simply be returned to the thread pool for reuse. ThreadPool contains the ability to access 25 available threads (per processor).

Using the ThreadPool class is far easier than creating threads using the Thread class as was shown earlier in this chapter. However, when deciding whether to create threads using the ThreadPool class or the Thread class, you should take some of the following points into consideration.

You should use the ThreadPool class when you are interested in achieving the following:

  • When you are interested in creating and destroying threads in the easiest manner possible

  • When the performance of how your application uses threads is of high priority

You should instead use the Thread class when you are interested in achieving the following:

  • When you are interested in controlling the priority of the threads created

  • When you want the thread you are working with to maintain its identity, which is associated with the thread over various operations and time intervals

  • When you are working with threads that might be long-lived threads

The following example looks at how to create a thread using the ThreadPool class. First, create a console application. The code for this application is as follows:

 using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace ConsoleApplication1 { class Program { static int interval; static void Main(string[] args) { Console.Write("Interval to display results at?> "); interval = int.Parse(Console.ReadLine()); ThreadPool.QueueUserWorkItem(new WaitCallback(StartMethod)); Thread.Sleep(100); ThreadPool.QueueUserWorkItem(new WaitCallback(StartMethod)); Console.ReadLine(); } static void StartMethod(Object stateInfo) { DisplayNumbers("Thread " + DateTime.Now.Millisecond.ToString()); Console.WriteLine("Thread Finished"); } static void DisplayNumbers(string GivenThreadName) { Console.WriteLine("Starting thread: " + GivenThreadName); for (int i = 1; i <= 8 * interval; i++) { if (i % interval == 0) { Console.WriteLine("Count has reached " + i); Thread.Sleep(1000); } } } } } 

The first thing to pay attention to is that the System.Threading namespace is imported into the page in order to gain access to the ThreadPool class. This example is similar to an earlier example used in this chapter. Instead of creating an instance of the Thread class (as was done earlier), you simply need to call the ThreadPool.QueueUserWorkItem() method. You can go about calling this method in a couple of ways. Shown above is one variation on making this call. Below is another method to use:

 ThreadPool.QueueUserWorkItem(new WaitCallback(StartMethod)); 

It would have also been possible to simply using the following construct:

 ThreadPool.QueueUserWorkItem(StartMethod); 

After the first invocation of the QueueUserWorkItem method, the main thread is put to sleep for 100 milliseconds before a second thread in the managed thread pool is used. You do this by simply using another instance of the QueueUserWorkItem method invocation.

When run, you will see results similar to the following in the console:

Interval to display results at?> 100 Starting thread: Thread 265 Count has reached 100 Starting thread: Thread 359 Count has reached 100 Count has reached 200 Count has reached 200 Count has reached 300 Count has reached 300 Count has reached 400 Count has reached 400 Count has reached 500 Count has reached 500 Count has reached 600 Count has reached 600 Count has reached 700 Count has reached 700 Count has reached 800 Count has reached 800 Thread Finished Thread Finished

When using the WaitCallBack delegate, you also have the ability to pass in a parameter as well. This is illustrated in this partial code example:

 ThreadPool.QueueUserWorkItem(new WaitCallback(StartMethod), "First Thread"); Thread.Sleep(100); ThreadPool.QueueUserWorkItem(new WaitCallback(StartMethod), "Second Thread"); Console.ReadLine();

As you can see, a string is also passed in with the WaitCallBack delegate. This is then used in the StartMethod method as illustrated here:

static void StartMethod(Object stateInfo) { DisplayNumbers("Thread " + stateInfo.ToString());      Console.WriteLine("Thread Finished"); }

These changes produce the following results:

Interval to display results at?> 100 Starting thread: Thread First Thread Count has reached 100 Starting thread: Thread Second Thread Count has reached 100 Count has reached 200 Count has reached 200 Count has reached 300 Count has reached 300 Count has reached 400 Count has reached 400 Count has reached 500 Count has reached 500 Count has reached 600 Count has reached 600 Count has reached 700 Count has reached 700 Count has reached 800 Count has reached 800 Thread Finished Thread Finished

It is also possible to get a series of properties about the thread you are working with using the Thread object. To pull some of the information on the thread being executed, change the DisplayNumbers method as follows:

static void DisplayNumbers(string GivenThreadName) {    Console.WriteLine("Starting thread: " + GivenThreadName);    for (int i = 1; i <= 8 * interval; i++)    {       if (i % interval == 0)       {          Console.WriteLine("Count has reached " + i); Console.WriteLine("CurrentCulture: " + Thread.CurrentThread.CurrentCulture.ToString()); Console.WriteLine("IsThreadPoolThread: " + Thread.CurrentThread.IsThreadPoolThread.ToString()); Console.WriteLine("ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString()); Console.WriteLine("Priority: " + Thread.CurrentThread.Priority.ToString()); Console.WriteLine("ThreadState: " + Thread.CurrentThread.ThreadState.ToString());          Thread.Sleep(1000);       }    } }

In this example, you use the Thread.CurrentThread property to get at the information available for the particular thread that is currently being executed. This will produce the following results (a partial sample of the output):

Count has reached 100 CurrentCulture: en-US IsThreadPoolThread: True ManagedThreadId: 10 Priority: Normal ThreadState: Background

Remember, in the end, you can create threads using the Thread or the ThreadPool class. Each one has some pros and cons, but you will find that it is pretty simple to work with .NET threading in any case.




Professional C# 2005
Pro Visual C++ 2005 for C# Developers
ISBN: 1590596080
EAN: 2147483647
Year: 2005
Pages: 351
Authors: Dean C. Wills

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net