Here’s a detailed hands-on exercise plan for mastering Concurrency and Parallel Programming in C# (2025). Each phase includes concepts, code examples, and exercises to help you solidify your skills.
🚀 Phase 1: Fundamentals of Multithreading in C#
Concepts to Learn:
✔ Understanding Threads and how the Thread class works
✔ Managing Thread Lifecycle (Start, Sleep, Join, Abort)
✔ Thread Synchronization (lock, Monitor, Mutex, Semaphore, AutoResetEvent, ManualResetEvent)
✔ Avoiding Race Conditions & Deadlocks
Exercise 1: Creating a Simple Thread
📌 Task: Create a new thread that prints numbers from 1 to 10.
✅ Goal: Understand how to create and start a thread.
using System;
using System.Threading;
class Program
{
static void PrintNumbers()
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"Thread: {i}");
Thread.Sleep(500); // Simulate work
}
}
static void Main()
{
Thread thread = new Thread(PrintNumbers);
thread.Start();
thread.Join(); // Wait for thread to finish
Console.WriteLine("Main Thread Exiting...");
}
}
Exercise 2: Thread Synchronization with lock
📌 Task: Create two threads that increment a shared counter.
✅ Goal: Prevent race conditions using lock
.
using System;
using System.Threading;
class Program
{
static int counter = 0;
static object lockObject = new object();
static void Increment()
{
for (int i = 0; i < 1000; i++)
{
lock (lockObject) // Prevent race condition
{
counter++;
}
}
}
static void Main()
{
Thread t1 = new Thread(Increment);
Thread t2 = new Thread(Increment);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine($"Final Counter: {counter}");
}
}
Exercise 3: Avoiding Deadlocks
📌 Task: Simulate a deadlock and fix it using proper lock ordering.
✅ Goal: Learn deadlock prevention strategies.
using System;
using System.Threading;
class Program
{
static object lock1 = new object();
static object lock2 = new object();
static void Thread1()
{
lock (lock1)
{
Thread.Sleep(100);
lock (lock2)
{
Console.WriteLine("Thread1 acquired both locks.");
}
}
}
static void Thread2()
{
lock (lock2)
{
Thread.Sleep(100);
lock (lock1) // Reversed order causes deadlock
{
Console.WriteLine("Thread2 acquired both locks.");
}
}
}
static void Main()
{
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
}
}
🔹 Fix: Ensure both threads lock objects in the same order.
🚀 Phase 2: Task-Based Asynchronous Programming (TAP)
Concepts to Learn:
✔ Understanding Task and Task.Run()
✔ Using ContinueWith()
for task chaining
✔ Implementing Parallel.ForEach and Parallel.Invoke
Exercise 1: Running Tasks in Parallel
📌 Task: Run multiple tasks concurrently.
✅ Goal: Understand Task.Run()
.
using System;
using System.Threading.Tasks;
class Program
{
static void TaskMethod()
{
Console.WriteLine($"Task Running on Thread {Task.CurrentId}");
}
static void Main()
{
Task t1 = Task.Run(TaskMethod);
Task t2 = Task.Run(TaskMethod);
Task.WaitAll(t1, t2);
Console.WriteLine("All tasks completed.");
}
}
Exercise 2: Using Parallel.ForEach
📌 Task: Process a list of numbers using Parallel.ForEach()
.
✅ Goal: Use PLINQ for faster processing.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Parallel.ForEach(numbers, number =>
{
Console.WriteLine($"Processing {number} on thread {Task.CurrentId}");
});
Console.WriteLine("Processing complete.");
}
}
🚀 Phase 3: Asynchronous Programming with async/await
Concepts to Learn:
✔ Async/Await Basics
✔ Task.Delay()
, ConfigureAwait(false)
✔ Handling Exceptions in Async Methods
Exercise 1: Making an Async HTTP Request
📌 Task: Fetch data from an API asynchronously.
✅ Goal: Learn awaiting I/O-bound operations.
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task FetchDataAsync()
{
using HttpClient client = new HttpClient();
string data = await client.GetStringAsync("https://jsonplaceholder.typicode.com/posts/1");
Console.WriteLine(data);
}
static async Task Main()
{
await FetchDataAsync();
}
}
Exercise 2: Async File Read
📌 Task: Read a file asynchronously.
✅ Goal: Learn I/O-bound async operations.
using System;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task ReadFileAsync(string path)
{
using StreamReader reader = new StreamReader(path);
string content = await reader.ReadToEndAsync();
Console.WriteLine(content);
}
static async Task Main()
{
await ReadFileAsync("test.txt");
}
}
🚀 Phase 4: Data Parallelism & PLINQ
Exercise: Parallel LINQ (PLINQ)
📌 Task: Filter large datasets using PLINQ
.
✅ Goal: Learn parallelized LINQ queries.
using System;
using System.Linq;
class Program
{
static void Main()
{
var numbers = Enumerable.Range(1, 100000);
var evenNumbers = numbers.AsParallel().Where(n => n % 2 == 0).ToList();
Console.WriteLine($"Total even numbers: {evenNumbers.Count}");
}
}
🚀 Phase 5: Advanced Concurrency
Exercise: Producer-Consumer Pattern
📌 Task: Implement a producer-consumer pattern using BlockingCollection
.
✅ Goal: Learn thread-safe queue processing.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static BlockingCollection<int> queue = new BlockingCollection<int>();
static void Producer()
{
for (int i = 0; i < 5; i++)
{
queue.Add(i);
Console.WriteLine($"Produced: {i}");
Thread.Sleep(100);
}
queue.CompleteAdding();
}
static void Consumer()
{
foreach (var item in queue.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed: {item}");
}
}
static void Main()
{
Task.Run(Producer);
Task.Run(Consumer).Wait();
}
}
Final Step: Real-World Projects
✔ Build a high-performance API
✔ Optimize concurrent processing in microservices
✔ Implement parallel image processing
🚀
Top comments (0)