C# & .NET Framework The .NET Grand Finale
💡
Exercise 46

Async/Await — The City's Parallel Construction 20 XP Hard

Ctrl+Enter Run Ctrl+S Save

⚡ Asynchronous Programming in C#

Imagine our .NET city is booming — dozens of buildings need to go up simultaneously. If we built them one at a time (synchronously), it would take forever. Instead, the city hires multiple crews that work in parallel, reporting back when each building is done.

That's exactly what async/await gives you: the ability to start long-running operations without blocking the main thread, then resume when results are ready.

🔑 Core Concepts

Task — represents an asynchronous operation that may or may not return a value.

Task<T> — represents an async operation that returns a value of type T.

async keyword — marks a method as asynchronous, allowing it to use await.

await keyword — suspends execution until the awaited Task completes, without blocking the thread.

// A simple async method async Task<string> BuildFloorAsync(string building, int floor) { await Task.Delay(100); // Simulate construction time return $"{building}: Floor {floor} done"; } // Calling it string result = await BuildFloorAsync("Tower A", 3);

🏗️ Task.Delay — Simulating Work

Task.Delay(ms) is the async equivalent of Thread.Sleep, but it does not block the thread. The thread is free to do other work while the delay elapses.

// BAD — blocks the thread Thread.Sleep(2000); // GOOD — releases the thread await Task.Delay(2000);

🚀 Task.WhenAll — Parallel Execution

Task.WhenAll takes multiple tasks and returns a single Task that completes when all of them finish. This is how we build multiple buildings at once.

Task buildA = BuildAsync("A", 3); Task buildB = BuildAsync("B", 5); // Both run concurrently — total time ≈ max(timeA, timeB) await Task.WhenAll(buildA, buildB); Console.WriteLine("All buildings done!");

🏎️ Task.WhenAny — First to Finish

Task.WhenAny completes as soon as any one of the tasks finishes — useful for timeouts or racing multiple data sources.

Task<string> fast = FetchFromCacheAsync(); Task<string> slow = FetchFromDatabaseAsync(); Task<string> winner = await Task.WhenAny(fast, slow); string data = await winner; // Get the result of whichever finished first

💡 Why Async Matters

  • Non-blocking I/O — File reads, HTTP calls, and DB queries don't freeze your app.
  • Responsive UIs — Desktop/mobile apps stay interactive during long operations.
  • Scalable servers — ASP.NET can handle thousands of concurrent requests because threads aren't wasted waiting.
  • Resource efficiency — Fewer threads needed, less memory consumed.

⚠️ Common Pitfalls

  • async void — Only use for event handlers. Exceptions in async void methods crash the process.
  • Blocking on async code — Never call .Result or .Wait() on a Task in a synchronous context — it can deadlock.
  • Forgetting await — If you don't await a Task, exceptions are silently swallowed and the operation may not complete before your method returns.
📋 Instructions
**The City's Parallel Construction** Build a program that constructs two buildings asynchronously: 1. Create an `async Task BuildAsync(string name, int floors)` method that: - Prints `"{name}: Started"` - Awaits `Task.Delay(100)` to simulate construction - Prints `"{name}: Complete! ({floors} floors)"` 2. In `Main`: - Print `"Starting construction..."` - Start **both** `BuildAsync("Building A", 3)` and `BuildAsync("Building B", 5)` tasks - Use `Task.WhenAll` to await both - Print `"All buildings done!"`
Define an async method `BuildAsync` that prints start, awaits Task.Delay(100), then prints complete. In Main, store both calls as Task variables (don't await them individually yet), then use `await Task.WhenAll(task1, task2)` to run them concurrently.
main.py
Hi! I'm Rex 👋
Output
Ready. Press ▶ Run or Ctrl+Enter.