Wie lösche ich das ConcurrentBag
? Es gibt keine Methode wie Clear
oder RemoveAll
...
Antworten:
Obwohl dies aufgrund einer möglichen Rennbedingung möglicherweise nicht vollständig klar ist, ist dies ausreichend:
while (!myBag.IsEmpty)
{
myBag.TryTake(out T _);
}
Update 10/03/2017: Wie @Lou richtig hervorhebt, ist die Zuweisung atomar. In diesem Fall Schaffung der ConcurrentBag
nicht atomar sein, aber diese Bezugnahme in die Variable setzen wird atomar sein - so Sperren oder Interlocked.Exchange
um ist es nicht unbedingt erforderlich ist .
Einige weiterführende Literatur:
Die Referenzzuweisung ist atomar. Warum wird Interlocked.Exchange (ref Object, Object) benötigt?
Ist eine Referenzzuweisung threadsicher?
Sie können jederzeit den Zugriff auf die Tasche selbst sperren und eine neue Instanz davon erstellen. Gegenstände in der Tasche sind dann für GC berechtigt, wenn nichts anderes daran festhält:
lock (something)
{
bag = new ConcurrentBag();
}
Oder wie Lukazoid betont:
var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Eine einfache Möglichkeit, den Inhalt abzulegen, setzt jedoch voraus, dass ein Objekt, wenn es Zugriff haben möchte, auch die Sperre erhält - dies kann teuer sein und die in sich ConcurrentBag
selbst vorgenommene Leistungsoptimierung negieren .
Wenn Sie wissen, dass zu diesem Zeitpunkt nichts anderes auf die Tasche zugreifen wird, beten Sie sie an und schließen Sie sie nicht ab :-)
bag = new
ungestraft tun ?
Interlocked.Exchange
kann besser sein als ein Schloss
Interlocked.Exchange
, wenn zum Zeitpunkt des Austauschs ein anderer Thread zum Beutel hinzugefügt wird? Wird das Add
während der gesperrt Exchange
?
Interlocked.Exchange
auch redundant (und bieten keine Thread-Sicherheit).
Die ausgewählte Antwort ist eine Art Problemumgehung, daher füge ich meine eigene Problemumgehung hinzu.
Meine Lösung bestand darin, alle verfügbaren Sammlungen im System.Collections.Concurrent- Namespace zu durchsuchen , um einen zu finden, in dem es trivial war, alle Elemente aus der Sammlung zu löschen.
Die ConcurrentStack- Klasse verfügt über eine Clear () -Methode, mit der alle Elemente aus der Auflistung entfernt werden. Tatsächlich ist dies (derzeit) die einzige Sammlung im Namespace, die dies tut. Ja, Sie müssen Push(T element)
statt Add(T element)
, aber ehrlich gesagt ist das die Zeitersparnis wert.
ConcurrentBag
? Ich kann keine native Eigenschaft oder Methode dafür sehen. Das Contains
zählt nicht. Es ist eine Erweiterungsmethode für generische IEnumerable
s und alles andere als effizient.
Im Sinne von Problemumgehungen .. ConcurrentDictionary<T, bool>
hat ein atomares Clear, ermöglicht es Ihnen aber auch schnell zu überprüfen, ob ein Schlüssel vorhanden ist. "Schnell" ist natürlich ein relativer Begriff, aber abhängig von Ihrer Verwendung ist er möglicherweise schneller als das Aufzählen eines großen Stapels.
Ab .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 gibt es eine Clear()
Methode für ConcurrentBag<T>
. Siehe: ConcurrentBag.Clear .