DEV Community

Cover image for Concurrency and Parallel Programming in C#: a detailed hands-on exercise plan
Taki
Taki

Posted on

Concurrency and Parallel Programming in C#: a detailed hands-on exercise plan

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..."); } } 
Enter fullscreen mode Exit fullscreen mode

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}"); } } 
Enter fullscreen mode Exit fullscreen mode

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(); } } 
Enter fullscreen mode Exit fullscreen mode

🔹 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."); } } 
Enter fullscreen mode Exit fullscreen mode

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."); } } 
Enter fullscreen mode Exit fullscreen mode

🚀 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(); } } 
Enter fullscreen mode Exit fullscreen mode

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"); } } 
Enter fullscreen mode Exit fullscreen mode

🚀 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}"); } } 
Enter fullscreen mode Exit fullscreen mode

🚀 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(); } } 
Enter fullscreen mode Exit fullscreen mode

Final Step: Real-World Projects

✔ Build a high-performance API

✔ Optimize concurrent processing in microservices

✔ Implement parallel image processing

🚀

Top comments (1)

Collapse
 
ngtduc693 profile image
Duc Nguyen Thanh

good topic