8.1 Multithreading Fundamentals
- Multithreading allows a program to execute multiple threads simultaneously, enabling parallel execution of code paths.
- A thread is an independent flow of execution within a process.
- By default, a C# application runs on a single thread (Main thread).
- Multithreading improves responsiveness, especially in UI apps and performance in multi-core processors.
- Threads share the same process memory but have their own stack and execution context.
- The System.Threading namespace contains classes and types for implementing multithreading.
8.2 Thread Class, Creating and Managing Threads
Creating Threads
- Use the
Threadclass from System.Threading to create and control threads. - Thread constructor accepts a method (using
ThreadStartorParameterizedThreadStartdelegates) to execute on the new thread. - Start a thread by calling
Start()method. - Examples:
using System;
using System.Threading;
class ThreadExample
{
static void PrintNumbers()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"PrintNumbers: {i} (Thread {Thread.CurrentThread.ManagedThreadId})");
Thread.Sleep(500);
}
}
static void Main()
{
Thread t1 = new Thread(PrintNumbers);
t1.Name = "WorkerThread";
t1.Start();
Console.WriteLine($"Main thread: {Thread.CurrentThread.ManagedThreadId}");
t1.Join(); // Wait for thread t1 to finish
}
}-
To pass parameters to threads, use
ParameterizedThreadStartor lambda expressions:
Thread t2 = new Thread(param =>
{
Console.WriteLine("Parameter received: " + param);
});
t2.Start("Hello Thread");
8.3 Threads Priority and Thread Synchronization
Thread Priority
- Threads have priority levels from
ThreadPriority.LowesttoThreadPriority.Highest. - Changing priority helps the scheduler decide which threads get processor time first.
- Set priority using
thread.Priority = ThreadPriority.AboveNormal;
Thread Synchronization
- Necessary to prevent race conditions and ensure thread-safe access to shared resources.
- Common synchronization primitives:
-
lockstatement (Monitor) -Mutex-Semaphore-AutoResetEvent/ManualResetEvent - Example with
lock:
class Counter
{
private int total = 0;
private readonly object locker = new object();
public void Increment()
{
lock (locker)
{
total++;
Console.WriteLine($"Total: {total}");
}
}
}8.4 Suspending, Resuming and Terminating Threads
Suspending and Resuming Threads (Not Recommended)
-
Methods like
Thread.Suspend()andThread.Resume()exist but are deprecated and can cause deadlocks. -
Use synchronization primitives (e.g.,
ManualResetEvent) to coordinate thread execution.
Terminating Threads
-
Thread.Abort()is also deprecated. -
Threads should be cooperatively cancelled using cancellation tokens or a shared flag.
Safe Alternative Example for Pause/Resume
class Worker
{
private ManualResetEventSlim _pauseEvent = new ManualResetEventSlim(true);
private bool _shouldStop = false;
public void DoWork()
{
while (!_shouldStop)
{
_pauseEvent.Wait();
Console.WriteLine("Working...");
Thread.Sleep(500);
}
Console.WriteLine("Worker stopped.");
}
public void Pause() => _pauseEvent.Reset();
public void Resume() => _pauseEvent.Set();
public void Stop() => _shouldStop = true;
}
Summary
| Aspect | Description |
| :— | :— |
| Multithreading | Multiple threads run concurrently within a process |
| Thread Class | Used to create, start, and manage threads |
| Thread Priority | Used to influence thread scheduling priority |
| Thread Synchronization | Prevents race conditions via locks, mutexes, semaphores, events |
| Suspending/Resuming Threads | Deprecated direct methods, use synchronization mechanisms instead |
| Terminating Threads | Avoid Abort(), prefer cooperative cancellation |