The Thread Class
The System.Threading.Thread class provides direct control over thread creation and management. While modern C# typically uses Tasks, understanding the Thread class helps you appreciate how async works under the hood.
Creating a Thread
There are several ways to create a thread:
Using a Named Method
csharp1void DoWork()2{3 Console.WriteLine("Working on thread: " + Thread.CurrentThread.ManagedThreadId);4}56Thread thread = new Thread(DoWork);7thread.Start();
Using a Lambda Expression
csharp1Thread thread = new Thread(() =>2{3 Console.WriteLine("Lambda running on thread: " + Thread.CurrentThread.ManagedThreadId);4});5thread.Start();
Passing Data to a Thread
csharp1// Using ParameterizedThreadStart2Thread thread = new Thread((obj) =>3{4 string message = (string)obj!;5 Console.WriteLine(message);6});7thread.Start("Hello from parameter!");89// Using closure (preferred)10string data = "Hello from closure!";11Thread thread2 = new Thread(() =>12{13 Console.WriteLine(data);14});15thread2.Start();
Essential Thread Methods
Start()
Begins execution of the thread:
csharp1Thread thread = new Thread(DoWork);2thread.Start(); // Thread begins executing DoWork
Join()
Blocks the calling thread until this thread completes:
csharp1Thread thread = new Thread(DoLongWork);2thread.Start();34// Do other work while thread runs...56thread.Join(); // Wait for thread to complete7Console.WriteLine("Thread finished!");
Join with Timeout
csharp1Thread thread = new Thread(DoLongWork);2thread.Start();34bool completed = thread.Join(5000); // Wait max 5 seconds5if (!completed)6{7 Console.WriteLine("Thread is still running after 5 seconds");8}
Sleep()
Pauses the current thread:
csharp1Thread.Sleep(1000); // Sleep for 1 second2Thread.Sleep(TimeSpan.FromSeconds(2)); // Sleep for 2 seconds
Thread Properties
csharp1Thread current = Thread.CurrentThread;23// Unique identifier for this thread4int id = current.ManagedThreadId;56// Thread name (useful for debugging)7current.Name = "WorkerThread";89// Is this a background thread?10bool isBackground = current.IsBackground;1112// Current state13ThreadState state = current.ThreadState;1415// Is thread still running?16bool isAlive = current.IsAlive;
Foreground vs Background Threads
csharp1// Foreground thread (default)2// App won't exit until this completes3Thread foreground = new Thread(DoWork);4foreground.Start();56// Background thread7// App can exit while this is running8Thread background = new Thread(DoWork);9background.IsBackground = true;10background.Start();
Important: The application terminates when all foreground threads complete. Background threads are terminated abruptly.
Complete Example
csharp1Console.WriteLine($"Main thread: {Thread.CurrentThread.ManagedThreadId}");23// Create multiple threads4Thread[] threads = new Thread[3];56for (int i = 0; i < 3; i++)7{8 int threadNumber = i; // Capture for closure9 threads[i] = new Thread(() =>10 {11 Console.WriteLine($"Thread {threadNumber} starting on {Thread.CurrentThread.ManagedThreadId}");12 Thread.Sleep(1000); // Simulate work13 Console.WriteLine($"Thread {threadNumber} finished");14 });15 threads[i].Name = $"Worker-{i}";16 threads[i].Start();17}1819// Wait for all threads to complete20foreach (Thread t in threads)21{22 t.Join();23}2425Console.WriteLine("All threads completed!");
Key Takeaways
Thread.Start()begins executionThread.Join()waits for completionThread.Sleep()pauses the current thread- Background threads don't prevent app exit
- Use closures carefully - capture loop variables properly
- Modern C# prefers Tasks over direct Thread usage