System.Threading Namespace
System.Threading
Assembly:
mscorlib
(in mscorlib.dll)
The System.Threading
namespace provides classes and interfaces that support multi-threaded programming.
Threading allows your application to perform multiple tasks concurrently. This can improve performance, responsiveness,
and scalability by enabling operations to run in the background without blocking the main execution thread.
Overview
Modern applications often need to perform operations that take a significant amount of time, such as network requests, file I/O, or complex calculations. Without threading, these operations would freeze the user interface and make the application appear unresponsive. Threading enables these operations to be executed on separate threads, allowing the main thread to continue handling user input and other foreground tasks.
Key concepts in this namespace include:
- Threads: The fundamental unit of execution within a process.
- Synchronization Primitives: Mechanisms to control access to shared resources and prevent race conditions.
- Thread Pooling: Reusing threads to reduce the overhead of creating and destroying them.
- Cancellation: Cooperative mechanisms to signal that an operation should be aborted.
Key Classes
Thread
Class
The Thread
class represents an operating system thread. You can create and manage threads explicitly using this class.
This gives you fine-grained control but also increases the complexity of managing thread lifecycles and synchronization.
using System;
using System.Threading;
public class Example
{
public static void WorkerMethod()
{
Console.WriteLine("Worker thread started.");
Thread.Sleep(2000); // Simulate work
Console.WriteLine("Worker thread finished.");
}
public static void Main(string[] args)
{
Thread worker = new Thread(WorkerMethod);
worker.Start(); // Start the thread
Console.WriteLine("Main thread continues.");
worker.Join(); // Wait for the worker thread to finish
Console.WriteLine("Main thread exiting.");
}
}
Monitor
Class
The Monitor
class provides static methods for obtaining mutual-exclusion locks on an object. It allows only one thread to execute
a critical section of code at a time, ensuring data integrity when multiple threads access shared resources.
using System;
using System.Threading;
public class BankAccount
{
private decimal balance = 1000;
private readonly object balanceLock = new object();
public void Withdraw(decimal amount)
{
lock (balanceLock) // Equivalent to Monitor.Enter/Exit
{
if (balance >= amount)
{
balance -= amount;
Console.WriteLine($"Withdrawal successful. New balance: {balance}");
}
else
{
Console.WriteLine("Insufficient funds.");
}
}
}
}
Mutex
Class
A Mutex
(mutual exclusion) is a synchronization primitive that can be used to synchronize access to a resource across multiple threads or processes.
It's heavier than a lock
and can be named, allowing synchronization between different applications.
Semaphore
and SemaphoreSlim
Classes
A Semaphore
limits the number of threads that can access a resource or pool of resources concurrently.
SemaphoreSlim
is a lighter-weight version for use within a single process.
AutoResetEvent
Class
An AutoResetEvent
is a synchronization primitive that allows one thread to signal one or more other threads that an event has occurred.
It automatically resets itself to the non-signaled state after a thread has been released.
ManualResetEvent
Class
A ManualResetEvent
is similar to AutoResetEvent
but does not reset itself automatically. It remains in the signaled state until explicitly reset.
This is useful for scenarios where multiple threads need to wait for the same event.
CountdownEvent
Class
The CountdownEvent
is a synchronization primitive that allows multiple threads to wait until a set of operations have completed.
A thread can signal that an operation is done, and the event will be signaled when the count reaches zero.
Barrier
Class
A Barrier
allows multiple threads to wait at a common point (a barrier) before proceeding. All threads must reach the barrier before any can continue.
Task
(System.Threading.Tasks)
While technically in the System.Threading.Tasks
namespace (introduced in .NET Framework 4.0), the Task
class and the Task Parallel Library (TPL)
provide a higher-level abstraction for asynchronous programming, often simplifying the use of threads.
CancellationTokenSource
CancellationTokenSource
is used to create and manage a CancellationToken
, which can be passed to operations to signal cancellation.
This is crucial for cooperative cancellation of long-running operations.
Best Practices
- Prefer using higher-level constructs like
Task Parallel Library (TPL)
orasync/await
over directThread
manipulation for most asynchronous operations. - Use synchronization primitives judiciously to avoid deadlocks and performance bottlenecks.
- Implement cancellation mechanisms to allow users to abort long-running operations gracefully.
- Consider thread pooling for scenarios where threads are frequently created and destroyed.
- Thoroughly test multi-threaded applications to identify and resolve race conditions and deadlocks.