⚡ 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!
[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!");
}
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
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!