C Sharp

A Multithreaded Application in C#

Before examining some of the different ways you can use threads in C#, let's see how easy it is to create a secondary thread in C#. After discussing the example, I'll look more closely at the System.Threading namespace and, specifically, the Thread class. In this example, I'm creating a second thread from the Main method. The method associated with the second thread then outputs a string showing that the thread has been called.

using System;
using System.Threading;
class SimpleThreadApp
    public static void WorkerThreadMethod()
        Console.WriteLine("Worker thread started");
    public static void Main()
        ThreadStart worker = new ThreadStart(WorkerThreadMethod);
        Console.WriteLine("Main - Creating worker thread");
        Thread t = new Thread(worker);
        ("Main - Have requested the start of worker thread");

If you compile and execute this application, you'll see that the message from the Main method prints before the message from the worker thread, proving that the worker thread is indeed working asynchronously. Let's dissect what's going on here.

The first new item to note is the inclusion of the using statement for the System.Threading namespace. We'll get to know that namespace shortly. For now, it's enough to understand that this namespace contains the different classes necessary for threading in the .NET environment. Now take a look at the first line of the Main method: -

    ThreadStart WorkerThreadMethod = new ThreadStart(WorkerThreadMethod);

Any time you see the following form, you can be sure that x is a delegate or-as you learned in Chapter 14, "Delegates and Event Handlers"-a definition of a method signature: -

x varName = new x (methodName);

So, we know that ThreadStart is a delegate. But it's not just any delegate. Specifically, it's the delegate that must be used when creating a new thread, and it's used to specify the method that you want called as your thread method. From there, I instantiate a Thread object where the constructor takes as its only argument a ThreadStart delegate, like so: -

Thread t = new Thread(worker);

After that, I call my Thread object's Start method, which results in a call to the WorkerThreadMethod.

That's it! Three lines of code to set up and run the thread and the thread method itself, and you're off and running. Now let's look deeper into the System.Threading namespace and its classes that make all this happen.