Monday, 22 September 2025

Concurrency

🟢 1️⃣ What is Concurrency?

Concurrency means doing multiple things at the same time, or overlapping tasks in your program.

  • In C#, this usually means using multiple threads or tasks.

  • Goal: make your program faster, or responsive (like not freezing UI).

Example:

  • Downloading 5 files at once instead of waiting for one file to finish before starting the next.


🟢 2️⃣ Ways to Achieve Concurrency in .NET Core

1. Task Parallel Library (TPL)

  • Use the Task class to run work asynchronously.

  • Example:

using System; using System.Threading.Tasks; class Program { static void Main() { Task t1 = Task.Run(() => Console.WriteLine("Task 1 running")); Task t2 = Task.Run(() => Console.WriteLine("Task 2 running")); Task.WaitAll(t1, t2); // wait until all tasks finish Console.WriteLine("All tasks done"); } }

Task.Run() runs work on a thread pool thread.


2. Async / Await

  • For IO-bound tasks (like reading files, HTTP calls), use async and await.

  • Example:

using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { HttpClient client = new HttpClient(); Task<string> t1 = client.GetStringAsync("https://example.com"); Task<string> t2 = client.GetStringAsync("https://example.org"); string[] results = await Task.WhenAll(t1, t2); foreach (var r in results) Console.WriteLine(r.Substring(0, 50)); } }
  • async/await does not block the thread, so the program can do other work while waiting.


3. Parallel Loops

  • Use Parallel.For or Parallel.ForEach to run loop iterations concurrently.

using System; using System.Threading.Tasks; class Program { static void Main() { Parallel.For(0, 5, i => { Console.WriteLine($"Processing {i} on thread {Task.CurrentId}"); }); } }
  • Automatically splits work across available CPU cores.


4. Concurrent Collections

  • When multiple threads access a collection, use thread-safe collections like:

using System; using System.Collections.Concurrent; using System.Threading.Tasks; class Program { static void Main() { ConcurrentBag<int> bag = new ConcurrentBag<int>(); Parallel.For(0, 10, i => bag.Add(i)); foreach (var item in bag) Console.WriteLine(item); } }
  • Other options: ConcurrentQueue, ConcurrentStack, ConcurrentDictionary.


5. Locks (Optional)

  • If you need to protect a resource, use lock:

class Counter { private int count = 0; private object lockObj = new object(); public void Increment() { lock(lockObj) { count++; } } }
  • Only one thread can access the block at a time.


🟢 3️⃣ Key Tips

  1. CPU-bound workTask.Run, Parallel.For

  2. IO-bound workasync/await

  3. Shared data → use Concurrent collections or lock

  4. Avoid blocking threads unnecessarily; async is usually better than Thread.Sleep.


🟢 4️⃣ Quick Summary Table

TypeWhen to UseExample
Task / TPLCPU-bound or simple backgroundTask.Run(() => DoWork())
Async / AwaitIO-bound (file, API, DB)await HttpClient.GetStringAsync(url)
Parallel.ForLoop with independent iterationsParallel.For(0, 10, i => ...)
ConcurrentCollectionMultiple threads accessing dataConcurrentBag<int>
LockProtect shared resourceslock(obj) { ... }

💡 Rule of Thumb:

  • Use async/await for non-CPU tasks.

  • Use Task / Parallel for CPU-heavy tasks.

  • Use concurrent collections to safely share data

No comments:

Post a Comment