Как удалить все элементы из ConcurrentBag? - PullRequest
66 голосов
/ 21 марта 2011

Как очистить ConcurrentBag? у него нет метода типа Clear или RemoveAll ...

Ответы [ 5 ]

57 голосов
/ 21 марта 2011

Обновление 10/03/2017: Как правильно указывает @Lou, назначение является атомарным. В этом случае создание ConcurrentBag не будет атомарным, но помещение этой ссылки в переменную будет атомарным - так что блокировка или Interlocked.Exchange вокруг нее строго не требуется.

Некоторое дальнейшее чтение:

присвоение ссылки является атомарным, так зачем нужен Interlocked.Exchange (ref Object, Object)?

Является ли справочное назначение безопасным для потоков?

<Ч />

Вы всегда можете заблокировать доступ к самой сумке и создать ее новый экземпляр. Предметы в сумке будут тогда понятны для GC, если на них ничего не держится:

lock (something)
{
    bag = new ConcurrentBag();
}

Или, как указывает Луказоид:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);

Простой способ связать содержимое, однако, это предполагает, что всякий раз, когда элемент хочет получить доступ, он также получает блокировку - это может быть дорого и может свести на нет настройку производительности, которая вошла в саму ConcurrentBag.

Если вы знаете, что больше ничего не получит доступ к сумке в это время, молитесь за нее и не запирайте: -)

32 голосов
/ 21 марта 2011
T someItem;
while (!myBag.IsEmpty) 
{
   myBag.TryTake(out someItem);
}
20 голосов
/ 26 июня 2013

Выбранный ответ является своего рода обходным путем, поэтому я добавляю свой собственный обходной путь.

Мое решение состояло в том, чтобы просмотреть все доступные коллекции в System.Collections.Concurrent. Пространство имен, чтобы найти то, где было тривиально удалить все элементы из коллекции.

Класс ConcurrentStack имеет метод Clear () , который удаляет все элементыиз коллекции.Фактически, это единственная коллекция в пространстве имен (в настоящее время), которая делает это.Да, вам нужно Push(T element) вместо Add(T element), но, честно говоря, это стоит сэкономленного времени.

9 голосов
/ 21 марта 2011

Вы можете удалить объект один за другим в цикле:

object result;
while (bag.TryTake(out result));

Обратите внимание, что мешок не обязательно будет пустым после этого цикла, потому что элементы могут быть добавлены после завершения цикла и до следующего операторадругая тема.

6 голосов
/ 12 сентября 2014

В духе обходных путей. ConcurrentDictionary<T, bool> имеет атомарную очистку, но также позволяет быстро проверить, существует ли ключ.«Быстро» - это, конечно, относительный термин, но в зависимости от вашего использования это может быть быстрее, чем перечисление большого стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...