• Starting Threads

    Creating a thread is very simple. Take a look at the following example:


    using System;
    using System.Threading;
    public class EntryPoint
    {
    private static void ThreadFunc()
    {
    Console.WriteLine("Hello from new thread {0}!",
    Thread.CurrentThread.GetHashCode());
    }
    static void Main()
    {
    // Create the new thread.
    Thread newThread =
    new Thread(new ThreadStart(EntryPoint.ThreadFunc));
    Console.WriteLine("Main Thread is {0}",
    Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine("Starting new thread...");
    // Start the new thread.
    newThread.Start();
    // Wait for new thread to finish.
    newThread.Join();
    Console.WriteLine("New thread has finished");
    }
    }



    All you have to do is create a new System.Thread object and pass an instance of the ThreadStart delegate as the parameter to the constructor. The ThreadStart delegate references a method that takes no parameters and returns no parameters. In the previous example, I chose to use the static ThreadFunc method as the start of execution for the new thread. I could have just as easily chosen to use any other method visible to the code creating the thread, as long as it neither accepted nor returned parameters. Notice that the code also outputs the managed thread identifier in two different ways to demonstrate how you can identify threads in the managed world. In the unmanaged C++ world, you would use the thread ID obtained via the Win32 API. In the managed world of .NET 1.1, you instead use the value returned by GetHashCode. As long as this thread is alive, it is guaranteed never to collide with any other thread in any application domain of this process. The thread hash code is not globally unique on the entire system. Starting with .NET 2.0, you can get the managed thread id by accessing the

    Thread.ManagedThreadId property. Also, you can see how you can get a reference to the current thread by accessing the static property Thread.CurrentThread. Finally, notice the call to the Join method on the newThread object. In native Win32 code, you normally wait for a thread to finish by waiting on its handle. When the thread finishes running, the operating system signals its handle and the wait completes. The Thread.Join method encapsulates this functionality. In this case, the code waits forever for the thread to finish. Thread.Join also provides a few overloads that allow you to specify a timeout period on the wait.

    When you create a separate thread, it is subject to the rules of the thread scheduler on the system, just like any other thread. However, sometimes you need to create threads that carry a little more or a little less weight when the scheduler algorithm is deciding which thread to execute next. You can control the priority of a managed thread via the Thread.Priority property. You can adjust this value as necessary during execution of the thread. It’s actually a rare occurrence that you’ll need to adjust this value. All threads start out with the priority of Normal from the ThreadPriority enumeration.

    There is some confusion in the MSDN documentation regarding whether one should call Thread.GetHashCode or access the Thread.ManagedThreadId property. If you read the MSDN documentation carefully, the summary page for System.Thread indicates that GetHashCode is what you should use to obtain the unique managed thread identifier during the duration the thread is alive. But if you look at the documentation for Thread.GetHashCode, it states that you should use the ManagedThreadId property instead. By debugging into the example application above using windbg in the Debugging Tools for Windows package in concert with the sos.dll debugger extension, I was able to determine that the results of GetHashCode and the ManagedThreadId property accessor both harvest the value from the same location within an internal structure of the Thread object instance. Arguably, ManagedThreadId makes the code easier to read because it’s more obvious what it is. Additionally, ManagedThreadId was introduced in .NET 2.0 and if you are targeting .NET 1.1, then you must use GetHashCode. I expect this confusion in the MSDN documentation to go away at some point soon, as it is a documentation bug. You should always rely upon ManagedThreadId even though GetHashCode returns the same value for the purposes of backwards compatibility. Throughout the rest of this chapter, I will be using ManagedThreadId rather than GetHashCode.


0 comments:

Leave a Reply