Datenstrukturen für die parallele Programmierung

.NET stellt mehrere Typen bereit, die für die parallele Programmierung nützlich sind. Darunter befinden sich eine Reihe von parallelen Auflistungsklassen, einfache Synchronisierungsprimitive und Typen für die verzögerte Initialisierung. Sie können diese Typen mit jedem Multithreadanwendungscode verwenden, einschließlich der Task Parallel Library und PLINQ.

Parallele Auflistungsklassen

Die Auflistungsklassen im Namespace System.Collections.Concurrent bieten threadsichere Vorgänge für das Hinzufügen und Entfernen. Diese vermeiden Sperren, wo immer dies möglich ist, und setzen differenzierte Sperren ein, wenn Sperren erforderlich sind. Eine parallele Auflistungsklasse benötigt beim Zugriff auf Elemente keinen Benutzercode für Sperren. Die parallelen Auflistungsklassen können die Leistung gegenüber Typen wie System.Collections.ArrayList und System.Collections.Generic.List<T> (mit benutzerimplementierter Sperre) in Szenarien, in denen mehrere Threads Elemente aus einer Auflistung hinzufügen und entfernen, erheblich verbessern.

In der folgenden Tabelle sind die parallelen Auflistungsklassen aufgeführt:

Geben Sie Folgendes ein: Beschreibung
System.Collections.Concurrent.BlockingCollection<T> Stellt Sperr- und Begrenzungsfunktionen für threadsichere Auflistungen bereit, die System.Collections.Concurrent.IProducerConsumerCollection<T> implementieren. Producerthreads werden blockiert, wenn keine Zeitfenster verfügbar sind oder wenn die Auflistung voll ist. Consumerthreads werden blockiert, wenn die Auflistung leer ist. Dieser Typ unterstützt auch nicht blockierenden Zugriff durch Consumer und Producer. BlockingCollection<T> kann als Basisklasse oder Sicherungsspeicher verwendet werden, um das Blockieren und Binden für jede Auflistungsklasse zu ermöglichen, die IEnumerable<T> unterstützt.
System.Collections.Concurrent.ConcurrentBag<T> Eine threadsichere Behälterimplementierung, die skalierbare Vorgänge zum Hinzufügen und Abrufen bietet.
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> Ein paralleler und skalierbarer Wörterbuchtyp
System.Collections.Concurrent.ConcurrentQueue<T> Eine parallele und skalierbare FIFO-Warteschlange
System.Collections.Concurrent.ConcurrentStack<T> Ein paralleler und skalierbarer LIFO-Stapel

Weitere Informationen finden Sie unter Threadsichere Auflistungen.

Synchronisierungsprimitiven

Die Synchronisierungsprimitiven im System.Threading-Namespace ermöglichen eine differenzierte Parallelität und schnellere Leistung durch das Vermeiden ressourcenintensiver Sperrmechanismen in Legacy-Multithreadingcode.

Die folgende Tabelle enthält die Synchronisierungstypen:

type BESCHREIBUNG
System.Threading.Barrier Ermöglicht mehreren Threads, parallel an einem Algorithmus zu arbeiten, indem ein Punkt bereitgestellt wird, an dem jeder Task seine Ankunft signalisieren und dann blockieren kann, bis einige oder alle Tasks angekommen sind. Weitere Informationen finden Sie unter Barrier.
System.Threading.CountdownEvent Vereinfacht Fork- und Join-Szenarien durch einen einfachen Rendezvousmechanismus. Weitere Informationen finden Sie unter CountdownEvent.
System.Threading.ManualResetEventSlim Eine Synchronisierungsprimitive, ähnlich wie System.Threading.ManualResetEvent. ManualResetEventSlim ist einfacher, kann aber nur für prozessinterne Kommunikation verwendet werden.
System.Threading.SemaphoreSlim Eine Synchronisierungsprimitive, die die Anzahl von Threads beschränkt, die parallel auf eine Ressource oder einen Ressourcenpool zugreifen können. Weitere Informationen finden Sie unter Semaphore und SemaphoreSlim.
System.Threading.SpinLock Eine gegenseitige Ausschlusssperrprimitive, durch die der Thread, der die Sperre zu erlangen versucht, für eine gewisse Zeit in einer Schleife warten (oder rotieren) muss, bevor er sein Quantum liefert. In Szenarien, in denen die Wartezeit für die Sperre nur kurz ist, bietet SpinLock eine bessere Leistung als andere Arten von Sperren. Weitere Informationen finden Sie unter SpinLock.
System.Threading.SpinWait Ein kleiner, einfacher Typ, der für eine bestimmte Zeit rotiert und schließlich den Thread in einen Wartezustand versetzt, wenn die Schleifenzahl überschritten wird. Weitere Informationen finden Sie unter SpinWait.

Weitere Informationen finden Sie unter

Klassen mit verzögerter Initialisierung

Bei einer verzögerten Initialisierung wird der Speicher für ein Objekt nicht zugewiesen, bis dieser benötigt wird. Eine verzögerte Initialisierung kann zur Verbesserung der Leistung beitragen, indem Objektzuweisungen über die Lebensdauer eines Programms hinweg verteilt werden. Sie können die verzögerte Initialisierung für jeden benutzerdefinierten Typ verwenden, indem Sie damit den Typ Lazy<T> umschließen.

Die folgende Tabelle enthält eine Auflistung der Typen für eine verzögerte Initialisierung:

type BESCHREIBUNG
System.Lazy<T> Stellt einfache, threadsichere verzögerte Initialisierung bereit.
System.Threading.ThreadLocal<T> Stellt einen Wert durch eine verzögerte Initialisierung auf Threadbasis bereit, wobei jeder Thread die Initialisierungsfunktion verzögert aufruft.
System.Threading.LazyInitializer Stellt statische Methoden bereit, durch die das Zuweisen einer dedizierten Instanz für die verzögerte Initialisierung nicht mehr erforderlich ist. Stattdessen werden Verweise eingesetzt, um sicherzustellen, dass Ziele initialisiert werden, sobald darauf zugegriffen wird.

Weitere Informationen finden Sie unter Verzögerte Initialisierung.

Aggregieren von Ausnahmen

Die System.AggregateException-Typ kann verwendet werden, um mehrere Ausnahmen zu erfassen, die in separaten Threads parallel ausgelöst und an den Verbindungsthread als eine einzelne Ausnahme zurückgegeben werden. Die Typen System.Threading.Tasks.Task und System.Threading.Tasks.Parallel sowie PLINQ verwenden hierzu sehr häufig AggregateException. Weitere Informationen finden Sie unter Ausnahmebehandlung und unter Vorgehensweise: Behandeln von Ausnahmen in einer PLINQ-Abfrage.

Siehe auch