System.Threading Namespace
Provides types that enable working with threads and managing concurrency in .NET applications. This namespace is fundamental for building responsive and scalable applications by allowing multiple operations to execute concurrently or in parallel.
Threads
The System.Threading.Thread
class represents a thread of execution in a process. You can create and manage threads to perform tasks concurrently.
Thread
Represents a thread of execution in a process.
ThreadState
Specifies the states of a thread.
ThreadPriority
Specifies the priority of a thread.
Example: Creating and Starting a Thread
using System;
using System.Threading;
public class ThreadExample
{
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 workerThread = new Thread(WorkerMethod);
workerThread.Start();
Console.WriteLine("Main thread continues.");
workerThread.Join(); // Wait for worker thread to complete
Console.WriteLine("Main thread finished.");
}
}
ThreadPool
The System.Threading.ThreadPool
class provides a pool of reusable threads that can be used to execute tasks. Using the thread pool is generally more efficient than creating individual threads, as it avoids the overhead of thread creation and destruction.
ThreadPool
Provides methods to create and manage threads from a pool.
WaitCallback
Represents a method to be executed by a thread pool thread.
Example: Using the ThreadPool
using System;
using System.Threading;
public class ThreadPoolExample
{
public static void ProcessItem(object state)
{
Console.WriteLine($"Processing item: {state} on thread {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
Console.WriteLine($"Finished processing item: {state}");
}
public static void Main(string[] args)
{
Console.WriteLine("Starting thread pool tasks...");
for (int i = 1; i <= 5; i++)
{
ThreadPool.QueueUserWorkItem(ProcessItem, $"Item {i}");
}
Console.WriteLine("All tasks queued. Main thread exiting.");
// In a real app, you'd likely have a way to wait for completion
}
}
Tasks
Introduced in .NET Framework 4, the System.Threading.Tasks
namespace provides a higher-level abstraction for asynchronous programming. The Task
and Task<TResult>
classes represent an asynchronous operation.
Task
Represents an asynchronous operation.
Task<TResult>
Represents an asynchronous operation that returns a value.
TaskFactory
Provides factory methods for creating and configuring tasks.
Example: Using Tasks
using System;
using System.Threading.Tasks;
public class TaskExample
{
public static async Task CalculateSumAsync(int max)
{
int sum = 0;
await Task.Delay(500); // Simulate async work
for (int i = 1; i <= max; i++)
{
sum += i;
}
Console.WriteLine($"Sum calculated: {sum}");
return sum;
}
public static async Task Main(string[] args)
{
Console.WriteLine("Starting task...");
Task sumTask = CalculateSumAsync(100);
Console.WriteLine("Doing other work while task runs...");
await Task.Delay(200); // Simulate other work
int result = await sumTask; // Wait for the task to complete and get the result
Console.WriteLine($"Final sum: {result}");
}
}
Synchronization Primitives
When multiple threads access shared resources, you need synchronization mechanisms to prevent race conditions and ensure data integrity. The System.Threading
namespace provides various synchronization primitives.
Mutex
A synchronization primitive that is a member of the Synchronization object.
Semaphore
A synchronization primitive that limits the number of threads that can access a resource or pool of resources concurrently.
lock statement
(C# feature) A convenient way to acquire a mutual-exclusion lock.
Interlocked
Provides atomic operations for variables that are shared by multiple threads.
Monitor
Provides synchronization mechanisms for multithreaded programming.
Example: Using `lock` for Synchronization
using System;
using System.Threading;
public class SynchronizationExample
{
private static int _counter = 0;
private static readonly object _lockObject = new object();
public static void IncrementCounter()
{
for (int i = 0; i < 100000; i++)
{
lock (_lockObject) // Acquire lock
{
_counter++;
} // Release lock
}
}
public static void Main(string[] args)
{
Thread t1 = new Thread(IncrementCounter);
Thread t2 = new Thread(IncrementCounter);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine($"Final counter value: {_counter}"); // Should be 200000
}
}
Async/Await Pattern
The async
and await
keywords in C# provide a powerful and concise way to write asynchronous code that looks synchronous. This pattern significantly simplifies handling I/O-bound and CPU-bound operations without blocking the main thread.
async
keyword
Marks a method as asynchronous.
await
keyword
Suspends execution of the async method until the awaited task completes.
Task/Task<TResult>
The return types commonly used with async methods.
Example: Using async/await for I/O Operations
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class AsyncAwaitExample
{
static readonly HttpClient client = new HttpClient();
public static async Task DownloadPageAsync(string url)
{
Console.WriteLine($"Downloading: {url}");
string content = await client.GetStringAsync(url);
Console.WriteLine($"Downloaded {url.Length} characters.");
return content;
}
public static async Task Main(string[] args)
{
Console.WriteLine("Starting asynchronous download...");
Task downloadTask = DownloadPageAsync("https://www.microsoft.com");
Console.WriteLine("Main thread is free to do other work...");
await Task.Delay(500); // Simulate other work
string html = await downloadTask;
Console.WriteLine($"Successfully downloaded content. First 100 chars: {html.Substring(0, Math.Min(100, html.Length))}");
}
}