Parallelität und Multithreading in C#: Fortgeschrittenes Niveau

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Parallelität und Multithreading in C#: Fortgeschrittenes Niveau



In der modernen C#-Entwicklung sind Parallelität und Multithreading nicht nur eine Erweiterung der Möglichkeiten, sondern grundlegende Werkzeuge zur Erstellung schneller, reaktionsfähiger und skalierbarer Anwendungen. Auf fortgeschrittenem Niveau gehen wir über das einfache Starten von Task.Run hinaus und stoßen auf die Feinheiten von Planern, Kontextsynchronisation und Patterns für die Arbeit mit gemeinsamen Daten. In diesem Artikel behandeln wir die wichtigsten fortgeschrittenen Konzepte der Parallelität in C# (.NET), die Ihnen helfen, effizienten und sicheren Code zu schreiben.



1. Task und ValueTask: Vertiefte Nutzung



Die Klasse Task ist die Grundlage der asynchronen Programmierung in C#. Auf fortgeschrittenem Niveau ist es jedoch wichtig, den Unterschied zwischen Task und ValueTask zu verstehen und den Lebenszyklus von Aufgaben zu verwalten.



Wann ValueTask verwenden?

ValueTask ist eine Struktur, die es ermöglicht, die Speicherzuweisung für ein Task-Objekt zu vermeiden, wenn das Ergebnis bereits synchron verfügbar ist. Dies ist entscheidend für Hochleistungsszenarien, z. B. in Caching-Methoden.



public class CacheService{    private readonly Dictionary<string, string> _cache = new();

public async ValueTask<string> GetDataAsync(string key) { if (_cache.TryGetValue(key, out string value)) { // Ergebnis ist bereits vorhanden, kein Task wird erstellt return value; }

// Asynchrones Abrufen von Daten string data = await FetchFromDatabaseAsync(key); _cache[key] = data; return data; }

private async Task<string> FetchFromDatabaseAsync(string key) { await Task.Delay(100); // Simulation einer Verzögerung return $"Data for {key}"; }}


Fortgeschrittene Fehlerbehandlung und Abbruch

Verwenden Sie CancellationToken für den korrekten Abbruch langer Operationen. Kombinieren Sie mehrere Token über CancellationTokenSource.CreateLinkedTokenSource.



public async Task ProcessWithTimeoutAsync(CancellationToken externalToken){    using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(5));    using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(externalToken, timeoutCts.Token);

try { await LongRunningOperationAsync(linkedCts.Token); } catch (OperationCanceledException) { Console.WriteLine("Operation abgebrochen oder Zeitüberschreitung."); }}


2. SynchronizationContext und Aufgabenplaner



Das Verständnis von SynchronizationContext ist für die Arbeit mit UI-Threads (WPF, WinForms) und ASP.NET Core erforderlich. Auf fortgeschrittenem Niveau können Sie eigene Synchronisationskontexte erstellen.



Kontext für den Threadpool konfigurieren

Standardmäßig erfasst await den aktuellen SynchronizationContext. Um dies zu vermeiden (und Deadlocks zu verhindern), verwenden Sie ConfigureAwait(false).



public async Task ProcessDataAsync(){    // Dieser Code wird im ursprünglichen Kontext ausgeführt (z. B. UI)    await Task.Run(() => HeavyComputation()).ConfigureAwait(false);

// Nach ConfigureAwait(false) — im Kontext des Threadpools // Kein Zugriff auf UI-Elemente! Console.WriteLine("Im Threadpool ausgeführt");}


Erstellen eines benutzerdefinierten Planers

Sie können Ihren eigenen TaskScheduler implementieren, z. B. um die Anzahl der gleichzeitig ausgeführten Aufgaben zu begrenzen (Analog zu SemaphoreSlim auf Planerebene).



public class LimitedConcurrencyTaskScheduler : TaskScheduler{    private readonly SemaphoreSlim _semaphore;    private int _runningTasks;

public LimitedConcurrencyTaskScheduler(int maxConcurrency) { _semaphore = new SemaphoreSlim(maxConcurrency);

Blogs

Buchempfehlungen