Подтвердить что ты не робот

Как удалить все элементы из ConcurrentBag?

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

4b9b3361

Ответ 1

T someItem;
while (!myBag.IsEmpty) 
{
   myBag.TryTake(out someItem);
}

Ответ 2

Обновление 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.

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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