Parallelität und Multithreading in C#: Von A bis Z – vollständiger Leitfaden

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

Einleitung: Warum ist Parallelität in C# notwendig?

Moderne Anwendungen erfordern zunehmend die gleichzeitige Ausführung mehrerer Operationen. Der Benutzer erwartet, dass die Oberfläche beim Laden von Daten nicht "einfriert" und der Server Tausende von Anfragen parallel verarbeiten kann. In C# (.NET) wird hierfür Parallelität – die Fähigkeit eines Programms, mehrere Aufgaben in überlappenden Zeitintervallen auszuführen – und Multithreading – die Umsetzung von Parallelität mit Hilfe mehrerer Ausführungsthreads – verwendet.

In diesem Artikel behandeln wir die wichtigsten Konzepte: von den grundlegenden Thread bis hin zu modernen async/await und Parallel. Sie erfahren, wie Sie das richtige Werkzeug für jede Aufgabe auswählen und typische Fehler wie Deadlocks und Race Conditions vermeiden.



1. Grundlagen: Thread und ThreadPool

Arbeiten mit Threads über Thread

Die Klasse System.Threading.Thread ist die niedrigste Ebene zum Erstellen von Threads. Jeder Thread hat einen eigenen Stack und wird unabhängig ausgeführt. Beispiel zum Erstellen und Starten eines Threads:

using System;using System.Threading;

class Program{ static void Main() { Thread thread = new Thread(DoWork); thread.Start(); // Der Hauptthread arbeitet weiter for (int i = 0; i < 5; i++) { Console.WriteLine($"Hauptthread: {i}"); Thread.Sleep(100); } thread.Join(); // Warten auf den Abschluss des Kindthreads }

static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine($"Arbeitsthread: {i}"); Thread.Sleep(150); } }}

Wichtig: Das Erstellen eines neuen Threads ist eine teure Operation. Für das häufige Erstellen kurzlebiger Threads ist es besser, ThreadPool zu verwenden.



ThreadPool – Thread-Pool

ThreadPool verwaltet einen Satz von Arbeitsthreads, die wiederverwendet werden. Dies ist effizienter, als Thread manuell zu erstellen. Beispiel:

ThreadPool.QueueUserWorkItem(state =>{    Console.WriteLine("Aufgabe wird im Thread-Pool ausgeführt");    Thread.Sleep(500);    Console.WriteLine("Aufgabe abgeschlossen");});

Console.WriteLine("Hauptthread arbeitet weiter");Console.ReadKey();

Einschränkung: Sie können die Priorität oder den Namen eines Threads aus dem Pool nicht direkt steuern. Für eine feinere Kontrolle verwenden Sie Task.



2. Task und Task Parallel Library (TPL)

Task – moderner Ansatz

Seit .NET 4.0 ist Task das wichtigste Werkzeug für asynchrone Operationen. Es abstrahiert Threads und ermöglicht die Arbeit mit Ergebnissen. Beispiel:

using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Task<int> task = Task.Run(() => ComputeResult(10)); // Andere Arbeit kann erledigt werden Console.WriteLine("Warte auf Ergebnis..."); int result = await task; Console.WriteLine($"Ergebnis: {result}"); }

static int ComputeResult(int value) { Task.Delay(1000).Wait(); // Simulation einer langen Operation return value * 2; }}

Wichtige Vorteile:

  • Gibt ein Ergebnis über Task<T> zurück
  • Unterstützt Abbruch über CancellationToken
  • Ermöglicht das Kombinieren von Aufgaben (ContinueWith, WhenAll, WhenAny)
  • Integriert mit async/await


Parallel – für parallele Schleifen

Die Klasse Parallel vereinfacht die Ausführung von Schleifen mit Parallelisierung. Beispiel:

using System;using System.Threading.Tasks;

class Program{ static void Main()\

Blogs

Buchempfehlungen