Creating Multi-Threading Applications with C#

Multi-threading allows more than one path of concurrent code to run, and on multi-core and multi-processor systems it speeds up processing.

By Tim Trott | C# ASP.Net MVC | November 10, 2007
809 words, estimated reading time 3 minutes.

The concept of multi-threading goes right the way down at the processor level. Single thread code has a single execution path on the processor, each line of code may represent several CPU instructions, and they are all executed sequentially. During a long-running operation, no other execution path will be run from the same application. Threading and multitasking are not related, multitasking is a feature of the operating system whereby it allocates processor time slices to allow multiple programs to access the CPU. Threading allows a program to execute two or more execution paths in parallel. Threading does not require a multi-processor multi-core processor to run.

Multi-threaded applications open up more instruction paths allowing two or more code paths to be run at the same time. This technique allows a long processing operation to run in the background, while the user interface runs in a separate thread. Alternatively, you can split a long job into two sections, or run two operations at the same time.

The .Net framework manages all the complexities of multithreaded applications; all you need to do is create a threading object and tell it what to do. It's literally that easy.

C#
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        doSomeWork();

        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Main Method Loop: " + i.ToString());

            / Delay so we can visibly see the work being done
            Thread.Sleep(1000);
        }
    }

    protected static void doSomeWork()
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("doSomeWork Loop: " + i.ToString());

            / A different delay so we can see the difference
            Thread.Sleep(500);
        }
    }
}

In this example, the main method calls the doSomeWork method which is processed, then it processes the for loop within the main. The resulting output is:

doSomeWork Loop: 0
doSomeWork Loop: 1
doSomeWork Loop: 2
doSomeWork Loop: 3
doSomeWork Loop: 4
doSomeWork Loop: 5
doSomeWork Loop: 6
doSomeWork Loop: 7
doSomeWork Loop: 8
doSomeWork Loop: 9
Main Method Loop: 0
Main Method Loop: 1
Main Method Loop: 2
Main Method Loop: 3
Main Method Loop: 4
Main Method Loop: 5
Main Method Loop: 6
Main Method Loop: 7
Main Method Loop: 8
Main Method Loop: 9
Press any key to continue . . .

If we want both loops to run at the same time we need to create a thread to run the doSomeWork method.

C#
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        ThreadStart threadWork = new ThreadStart(doSomeWork);
        Thread thread = new Thread(threadWork);
        thread.Start();

        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Main Method Loop: " + i.ToString());

            / Delay so we can visibly see the work being done
            Thread.Sleep(1000);
        }
    }

    protected static void doSomeWork()
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("doSomeWork Loop: " + i.ToString());

            / A different delay so we can see the difference
            Thread.Sleep(500);
        }
    }
}
Main Method Loop: 0
doSomeWork Loop: 0
doSomeWork Loop: 1
Main Method Loop: 1
doSomeWork Loop: 2
doSomeWork Loop: 3
Main Method Loop: 2
doSomeWork Loop: 4
doSomeWork Loop: 5
Main Method Loop: 3
doSomeWork Loop: 6
doSomeWork Loop: 7
Main Method Loop: 4
doSomeWork Loop: 8
doSomeWork Loop: 9
Main Method Loop: 5
Main Method Loop: 6
Main Method Loop: 7
Main Method Loop: 8
Main Method Loop: 9
Press any key to continue . . .

Now when you run the program you will notice that the main loop and the doSomeWork loop are now both running at the same time.

The Thread.Sleep is there purely so you can see each line is written on the screen. You can remove it and the program will run and complete instantly. The parameter value is the time to delay in Milliseconds (1000ms = 1 sec.)

When to use Multi-Threading

Multi-threading should not be used because it is seen to be cool, it should only be used when there is a real need for it. Threaded applications soon become a minefield of debugging hell. Threads are unpredictable, and results can be turned into garbage if it's not done properly. Imagine two threads running, A and B. A depends on a value S to perform a calculation. What happens if thread B changes the value of S while A is still running?

Threading should only be considered if the time taken to perform the calculation in series is unacceptably slow, or if two tasks are unconnected and able to run parallel. You should also ensure that all resources are capable of supporting multiple concurrent connections. Can the database server accept two update commands at the same time or is it working in table-lock mode?

Only when you are comfortable that threading is the only way forward should you go down this route.

Multi-Threading and Thread Safety

Thread safe code protects the thread from some of the problems outlined above. Thread safety highlights the inherent weakness of a multi-thread system: the need for multiple threads to access the same shared data, but not at the same time.

How to tell if the code is threading safe? Does the thread access data on the heap or any global variables? Does it access any data through references or pointers? Is it reliant on a file, database connection or similar to be present?

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

There are no comments yet. Why not get the discussion started?

We respect your privacy, and will not make your email public. Learn how your comment data is processed.