Jak wyczyścić ConcurrentBag? nie ma żadnej metody takiej jak Clearlub 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 ConcurrentBagwill 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 = newbezkarnie?
Interlocked.Exchangemoże być lepszy niż zamek
Interlocked.Exchangedziała, jeśli w momencie wymiany do torby dodaje się kolejną nitkę? Czy to Addsię blokuje w trakcie Exchange?
Interlocked.Exchangesą 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 Containssię nie liczy. Jest to metoda rozszerzająca dla ogólnych IEnumerables 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 .