Jak wyczyścić ConcurrentBag
? nie ma żadnej metody takiej jak Clear
lub RemoveAll
...
c#
concurrency
PawanS
źródło
źródło
Odpowiedzi:
Chociaż może to nie być całkowicie jasne ze względu na potencjalny stan wyścigu, jest to wystarczające:
while (!myBag.IsEmpty) { myBag.TryTake(out T _); }
źródło
Aktualizacja 10/03/2017: Jak słusznie wskazuje @Lou, przypisanie jest niepodzielne. W tym przypadku utworzenie
ConcurrentBag
will nie będzie atomowe, ale umieszczenie tego odniesienia w zmiennej będzie atomowe - czyli zablokowanie lubInterlocked.Exchange
otaczanie go nie jest ściśle wymagane.Dalsze czytanie:
przypisanie odniesienia jest niepodzielne, więc dlaczego potrzebne jest Interlocked.Exchange (ref Object, Object)?
Czy przypisanie odwołania jest bezpieczne dla wątków?
Zawsze możesz zablokować dostęp do samej torby i utworzyć jej nową instancję. Przedmioty w torbie będą wtedy kwalifikowały się do GC, jeśli nic innego ich nie trzyma:
lock (something) { bag = new ConcurrentBag(); }
Lub, jak wskazuje Lukazoid:
var newBag = new ConcurrentBag(); Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Łatwy sposób na przechowywanie zawartości, jednak zakłada to, że gdy element chce uzyskać dostęp, również zostaje zablokowany - może to być kosztowne i może zniweczyć dostrojenie wydajności, które zaszło w
ConcurrentBag
samego siebie.Jeśli wiesz, że w tej chwili nic innego nie będzie miało dostępu do torby, złóż ją i nie zamykaj :-)
źródło
bag = new
bezkarnie?Interlocked.Exchange
może być lepszy niż zamekInterlocked.Exchange
działa, jeśli w momencie wymiany do torby dodaje się kolejną nitkę? Czy toAdd
się blokuje w trakcieExchange
?Interlocked.Exchange
są tutaj nadmiarowe (i nie zapewniają bezpieczeństwa wątków).Wybrana odpowiedź jest pewnego rodzaju obejściem, więc dodaję własne obejście.
Moim rozwiązaniem było przejrzenie wszystkich dostępnych kolekcji w przestrzeni nazw System.Collections.Concurrent, aby znaleźć taką, w której wyczyszczenie wszystkich elementów z kolekcji było trywialne.
ConcurrentStack klasa ma clear () metodę, która usuwa wszystkie elementy z tej kolekcji. W rzeczywistości jest to jedyna kolekcja w przestrzeni nazw (obecnie), która to robi. Tak, musisz
Push(T element)
zamiast tegoAdd(T element)
, ale szczerze mówiąc, warto zaoszczędzić czas.źródło
ConcurrentBag
? Nie widzę żadnej natywnej właściwości ani metody, aby to zrobić. ToContains
się nie liczy. Jest to metoda rozszerzająca dla ogólnychIEnumerable
s i nie jest skuteczna.W duchu obejść ..
ConcurrentDictionary<T, bool>
posiada atomic Clear, ale pozwala też szybko sprawdzić czy klucz istnieje. „Szybko” to oczywiście termin względny, ale w zależności od zastosowania może być szybszy niż wyliczanie dużego stosu.źródło
Od wersji .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 dostępna jest
Clear()
metodaConcurrentBag<T>
. Zobacz: ConcurrentBag.Clear .źródło
int cnt = _queue.Count; for (; cnt > 0; cnt--) { _queue.TryDequeue(out img); }
Nie wpada w nieskończoną pętlę i oczyszcza zawartość obecnego czasu.
źródło