Threads in C#
Last updated: Thu May 08 2025
Multithreading is a powerful feature in operating system that allows your program to perform multiple tasks concurrently. In today’s multi-core processor world, threading can significantly boost the responsiveness and performance of your applications.
What is a Thread?
A thread is the smallest unit of execution within a process. By default, every C# application starts with a main thread, and you can create additional threads to run tasks in parallel(or concurrently).
Creating a Thread in C#
You can use the System.Threading namespace to work with threads:
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread t = new Thread(PrintNumbers);
t.Start();
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Main thread: {i}");
Thread.Sleep(500);
}
}
static void PrintNumbers()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Worker thread: {i}");
Thread.Sleep(500);
}
}
}
Output (Interleaved):
Main thread: 0
Worker thread: 0
Main thread: 1
Worker thread: 1
...
Key Concepts
1. Thread.Start()
Starts the execution of the thread.
2. Thread.Sleep(milliseconds)
Pauses the thread for a specific time.
3. Thread.Join()
Blocks the calling thread until the called thread terminates.
4. Thread Safety
When multiple threads access shared resources, you must handle race conditions and ensure thread safety using locks or concurrent collections.
lock (locker)
{
// critical section
}
When to Use Threads
- ✅ Background processing
- ✅ UI responsiveness (e.g., WinForms, WPF)
- ✅ Parallel I/O operations
- ✅ Real-time monitoring or polling
When Not to Use Raw Threads
Instead of manually managing threads, consider higher-level alternatives like:
- Task Parallel Library (TPL) –
Task.Run(),Parallel.For - async/await – For async I/O-bound operations
- ThreadPool – For short-lived, frequent background tasks
Tools & Alternatives
System.Threading.ThreadSystem.Threading.Tasks.TaskSystem.Threading.ThreadPoolSystem.Threading.Mutex,Monitor,lock(for synchronization)
Final Thoughts
While threads offer fine-grained control, they come with complexity and risk (like deadlocks or race conditions). In most real-world scenarios, prefer using the Task library or async/await unless you specifically need to manage thread lifecycles.
Threads are like sharp knives—powerful but dangerous when misused. Use them wisely.