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.

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 are all executed sequentially. During a long-running operation, no other execution path will be run from the same application.
Threading and multitasking are unrelated; multitasking is a feature of the operating system that 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.
Multithreaded applications open up more instruction paths, allowing two or more code paths to run simultaneously. 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 simultaneously.
The .Net framework manages all the complexities of multithreaded applications; you only need to create a threading object and tell it what to do. It's that easy.
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 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 simultaneously we need to create a thread to run the doSomeWork method.
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 . . .
When you run the program, you will notice that the main loop and the doSomeWork loop are both running simultaneously.
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 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 can support multiple concurrent connections. Can the database server accept two update commands simultaneously, 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?