⚡ Lehrpfad 3: LINQ, Generics & Async/Await

C# 11: Asynchrone Programmierung mit async & await

Erstelle hochperformante, nicht-blockierende Cloud-Dienste: Meistere Task, Task<T>, parallele Ausführung mit Task.WhenAll und kooperativen Abbruch mit CancellationToken.

📂 Dateien dieser Lerneinheit:
📄 Aufgabe.cs (Startercode) 🧪 TestAufgabe.cs (xUnit Tests) 💡 Musterloesung.cs (Lösung) 📖 README.md

⚡ 1. Warum Asynchronität? Nicht-blockierende I/O

Wenn ein Server auf eine Datenbankabfrage oder einen HTTP-Request wartet, blockiert synchroner Code den Betriebssystem-Thread. In C# gibt await den Thread sofort an den .NET ThreadPool zurück, damit er andere Anfragen bearbeiten kann!

[Synchron: 3 Requests sequenziell] ── Req 1 (100ms) ──► Req 2 (100ms) ──► Req 3 (100ms) ──► Dauer: 300ms (1 Thread blockiert)
[Asynchron: Task.WhenAll Fan-Out] ──┬──► Task 1 (100ms) ──┐
                                  ├──► Task 2 (100ms) ──┼──► Task.WhenAll ──► Dauer: ~100ms (0 Threads blockiert!)
                                  └──► Task 3 (100ms) ──┘
// Paralleler Abruf mehrerer Microservices mit Task.WhenAll:
public async Task<List<ServiceResponse>> FetchAllAsync(IEnumerable<string> urls, CancellationToken ct)
{
    var tasks = urls.Select(url => FetchSingleServiceAsync(url, ct));
    var results = await Task.WhenAll(tasks);
    return results.ToList();
}

🛑 2. Kooperativer Abbruch mit CancellationToken

In verteilten Enterprise-Systemen kann ein Benutzer die Verbindung trennen oder ein Timeout ablaufen. Statt Threads gewaltsam abzubrechen, prüft der asynchrone Code regelmäßig ct.ThrowIfCancellationRequested():

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // Timeout nach 5s
try
{
    var data = await DownloadLargeFileAsync("https://api.enterprise.com/data", cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Download wurde durch Timeout abgebrochen!");
}
🏢 Didaktische Analogie: Das Restaurant-Pagersystem

Anstatt am Tresen zu stehen und die Küche zu blockieren (synchrones Warten), erhält der Gast einen Pager (Task) und setzt sich an den Tisch (Thread frei). Sobald das Gericht fertig ist, piept der Pager (await weckt die Fortsetzung auf).

📑 3. Cheat-Sheet: Async & Task Best Practices

Pattern / API Empfohlen (Best Practice) Gefährlich (Anti-Pattern)
Rückgabetyp ohne Rückgabewert public async Task DoWorkAsync() public async void DoWorkAsync() (Unabfangbare Crashes!)
Auf Ergebnis warten var res = await GetAsync(); var res = GetAsync().Result; (Deadlock-Gefahr!)
Mehrere Tasks parallel await Task.WhenAll(task1, task2); await task1; await task2; (Läuft sequenziell statt parallel!)
Abbruch / Timeout CancellationToken durchreichen Abbrüche ignorieren und Ressourcen weiter verschwenden

🎯 Aufgaben & Checkliste in Aufgabe.cs

💡 Cloud-Architektur Pro-Tipp: Async All The Way

Mische niemals synchronen blockierenden Code (.Wait(), .Result) mit asynchronem Code (async/await). In ASP.NET Core führt das unter Last unvermeidlich zum sogenannten Thread Pool Starvation Deadlock!

💻 In Web-IDE öffnen → Weiter zu C# 12: Exceptions →