Wie lösche ich das ConcurrentBag
? Es gibt keine Methode wie Clear
oder RemoveAll
...
c#
concurrency
PawanS
quelle
quelle
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 _); }
quelle
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 oderInterlocked.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 :-)
quelle
bag = new
ungestraft tun ?Interlocked.Exchange
kann besser sein als ein SchlossInterlocked.Exchange
, wenn zum Zeitpunkt des Austauschs ein anderer Thread zum Beutel hinzugefügt wird? Wird dasAdd
während der gesperrtExchange
?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)
stattAdd(T element)
, aber ehrlich gesagt ist das die Zeitersparnis wert.quelle
ConcurrentBag
? Ich kann keine native Eigenschaft oder Methode dafür sehen. DasContains
zählt nicht. Es ist eine Erweiterungsmethode für generischeIEnumerable
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.quelle
Ab .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 gibt es eine
Clear()
Methode fürConcurrentBag<T>
. Siehe: ConcurrentBag.Clear .quelle
int cnt = _queue.Count; for (; cnt > 0; cnt--) { _queue.TryDequeue(out img); }
Es fällt nicht in eine Endlosschleife und löscht den Inhalt der Gegenwart.
quelle