Jak wyczyścić ConcurrentBag
? nie ma żadnej metody takiej jak Clear
lub RemoveAll
...
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 _);
}
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:
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 :-)
bag = new
bezkarnie?
Interlocked.Exchange
może być lepszy niż zamek
Interlocked.Exchange
działa, jeśli w momencie wymiany do torby dodaje się kolejną nitkę? Czy to Add
się blokuje w trakcie Exchange
?
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 tego Add(T element)
, ale szczerze mówiąc, warto zaoszczędzić czas.
ConcurrentBag
? Nie widzę żadnej natywnej właściwości ani metody, aby to zrobić. To Contains
się nie liczy. Jest to metoda rozszerzająca dla ogólnych IEnumerable
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.
Od wersji .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 dostępna jest Clear()
metoda ConcurrentBag<T>
. Zobacz: ConcurrentBag.Clear .