Gewusst wie: Hinzufügen und Entfernen von Elementen aus einem ConcurrentDictionary

Dieses Beispiel zeigt, wie Elemente hinzugefügt, abgerufen, aktualisiert und von einer System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> entfernt werden. Diese Auflistungsklasse ist eine threadsichere Implementierung. Es empfiehlt sich, diese Klasse immer dann zu verwenden, wenn möglicherweise mehrere Threads gleichzeitig versuchen, auf Elemente zuzugreifen.

ConcurrentDictionary<TKey,TValue> bietet verschiedene praktische Methoden, mit denen der Code nicht mehr zuerst prüfen muss, ob ein Schlüssel vorhanden ist, bevor versucht wird, Daten hinzuzufügen oder zu entfernen. Die folgende Tabelle führt diese praktischen Methoden auf und beschreibt ihre Verwendung.

Methode Wenn folgende Bedingungen vorliegen
AddOrUpdate Sie möchten einen neuen Wert für einen angegebenen Schlüssel hinzufügen und, wenn der Schlüssel bereits vorhanden ist, den Wert ersetzen.
GetOrAdd Sie möchten den vorhandenen Wert für einen angegebenen Schlüssel abrufen und, wenn der Schlüssel nicht vorhanden ist, ein Schlüssel-Wert-Paar angeben.
TryAdd, TryGetValue , TryUpdate , TryRemove Sie möchten ein Schlüssel-Wert-Paar hinzufügen, abrufen, aktualisieren oder entfernen und, wenn der Schlüssel bereits vorhanden ist oder der Versuch aus einem anderen Grund fehlschlägt, eine alternative Aktion durchführen.

Beispiel

Im folgenden Beispiel werden zwei Instanzen von Task verwendet, um ConcurrentDictionary<TKey,TValue> parallel einige Elemente hinzuzufügen und dann den gesamten Inhalt auszugeben, um zu zeigen, dass die Elemente erfolgreich hinzugefügt wurden. Das Beispiel zeigt auch, wie die Methoden AddOrUpdate, TryGetValue und GetOrAdd zum Hinzufügen, Aktualisieren und Abrufen von Elementen aus der Auflistung verwendet werden.

[!code-csharpCDS#16] [!code-vbCDS#16]

ConcurrentDictionary<TKey,TValue> wurde für Multithread-Szenarios entworfen. Sie müssen keine Sperren in Ihrem Code verwenden, um Elemente zur Auflistung hinzuzufügen oder daraus zu entfernen. Es ist jedoch immer möglich, dass ein Thread einen Wert abruft und ein anderer Thread durch Zuweisen eines neuen Werts zum gleichen Schlüssel die Auflistung unmittelbar danach aktualisiert.

Darüber hinaus sind zwar alle Methoden von ConcurrentDictionary<TKey,TValue> threadsicher, aber nicht alle Methoden sind atomisch – insbesondere GetOrAdd und AddOrUpdate. Der an diese Methoden übergebene Benutzerdelegat wird außerhalb der internen Sperre des Wörterbuchs aufgerufen. (Dies erfolgt, um zu verhindern, dass unbekannter Code alle Threads blockiert.) Daher ist es möglich, dass die folgende Ereignissequenz eintritt:

1) threadA ruft GetOrAdd auf, findet kein Element und erstellt ein neues hinzuzufügendes Element durch Aufrufen des valueFactory-Delegaten.

2) threadB ruft GetOrAdd gleichzeitig auf, der zugehörige valueFactory-Delegat wird aufgerufen und erreicht die interne Sperre vor threadA. Daher wird das neue Schlüssel-Wert-Paar dieses Threads zum Wörterbuch hinzugefügt.

3) Der Benutzerdelegat von threadA wird fertiggestellt, und der Thread erreicht die Sperre, stellt jetzt aber fest, dass das Element bereits vorhanden ist.

4) threadA führt einen „Get“ aus und gibt die Daten zurück, die zuvor von threadB hinzugefügt worden waren.

Daher ist nicht garantiert, dass die von GetOrAdd zurückgegebenen Daten die gleichen Daten sind, die von der valueFactory des Threads erstellt wurden. Eine ähnliche Abfolge von Ereignissen kann eintreten, wenn AddOrUpdate aufgerufen wird.

Siehe auch

System.Collections.Concurrent
threadsichere Auflistungen