Multithreading is one of the most powerful concepts in programming. Using multithreading, you can break a complex task in a single application into multiple threads that execute independently of one another. One particularly good use of multithreading is in tasks that are synchronous in nature, such as Web Services calls. By default, Web Services calls are blocking calls — that is, the caller code does not continue until the Web Service returns the result. Because Web Services calls are often slow, this can result in sluggish client-side performance unless you take special steps to make the call an asynchronous one.
To see how multithreading works, first take a look at the following example:
class Program {
static void Main(string[] args) {
DoSomething();
Console.WriteLine('Continuing with the execution...');
Console.ReadLine();
}
static void DoSomething() {
while (true) {
Console.WriteLine('Doing something...');
}
}
}
This is a simple application that calls the DoSomething()
function to print out a series of strings (in fact, it is an infinite loop, which will never stop; see Figure 10-1). Right after calling the DoSomething()
function, you try to print a string ('Сontinuing with the execution...
') to the console window. However, because the DoSomething()
function is busy printing its own output, the 'Console.WriteLine('Continuing with the execution...');
' statement never gets a chance to execute.

Figure 10-1
This example illustrates the sequential nature of application — statements are executed sequentially. The DoSomething()
function is analogous to consuming a Web Service, and as long as the Web Service does not return a value to you (due to network latency or busy web server, for instance), the rest of your application is blocked (that is, not able to continue).
Starting a Thread
You can use threads to break up statements in your application into smaller chunks so that they can be executed in parallel. You could, for instance, use a separate thread to call the DoSomething()
function in the preceding example and let the remaining of the code continue to execute.
Every application contains one main thread of execution. A multithreaded application contains two or more threads of execution.
In C#, you can create a new thread of execution by using the Thread
class found in the System.Threading
namespace. The Thread
class creates and controls a thread. The constructor of the Thread
class takes in a ThreadStart
delegate, which wraps the function that you want to run as a separate thread. The following code shows to use the Thread
class to run the DoSomething()
function as a separate thread:
Import the System.Threading
namespace when using the Thread
class.
class Program {
static void Main(string[] args) {
Console.WriteLine('Continuing with the execution...');
Console.ReadLine();
}
static void DoSomething() {
while (true) {
Console.WriteLine('Doing something...');
}
}
}
Note that the thread is not started until you explicitly call the Start()
method. When the Start()
method is called, the DoSomething()
function is called and control is immediately returned to the Main()
function. Figure 10-2 shows the output of the example application.

Figure 10-2
Figure 10-3 shows graphically the two different threads of execution.

Figure 10-3
As shown in Figure 10-2, it just so happens that before the DoSomething()
method gets the chance to execute, the main thread has proceeded to execute its next statements. Hence, the output shows the main thread executing before the DoSomething()
method. In reality, both threads have an equal chance of executing, and one of the many possible outputs could be:
Doing something...
Doing something...
Continuing with the execution...
Doing something...
Doing something...
...
A thread executes until:
□ It reaches the end of its life (method exits), or
□ You prematurely kill (abort) it.
Aborting a Thread
You can use the Abort()
method of the Thread
class to abort a thread after it has started executing. Here's an example:
class Program {
static void Main(string[] args) {