Как очистить ConcurrentBag
? у него нет такого метода, как Clear
или RemoveAll
...
c#
concurrency
PawanS
источник
источник
Ответы:
Хотя это может быть не полностью очищено из-за потенциального состояния гонки, этого достаточно:
while (!myBag.IsEmpty) { myBag.TryTake(out T _); }
источник
Обновление 10/03/2017: как правильно указывает @Lou, назначение является атомарным. В этом случае создание объекта
ConcurrentBag
не будет атомарным, но помещение этой ссылки в переменную будет атомарным, поэтому блокировка или блокировкаInterlocked.Exchange
не требуется.Дальнейшее чтение:
присвоение ссылки является атомарным, так зачем нужен Interlocked.Exchange (ref Object, Object)?
Является ли задание ссылки потокобезопасным?
Вы всегда можете заблокировать доступ к самой сумке и создать ее новый экземпляр. После этого предметы в сумке будут доступны для сборки мусора, если за них больше ничего не держится:
lock (something) { bag = new ConcurrentBag(); }
Или, как указывает Луказоид:
var newBag = new ConcurrentBag(); Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Тем не менее, простой способ поместить содержимое в корзину. При этом предполагается, что всякий раз, когда элементу требуется доступ, он также получает блокировку - это может быть дорого и может свести на нет настройку производительности, которая вошла в
ConcurrentBag
саму себя.Если вы знаете, что в это время к сумке никто не получит доступ, молитесь и молитесь и не закрывайте ее :-)
источник
bag = new
безнаказанно?Interlocked.Exchange
может быть лучше замкаInterlocked.Exchange
работает, если во время обмена в корзину добавляется другой поток? ЭтоAdd
заблокировано во времяExchange
?Interlocked.Exchange
избыточность (и не обеспечивают безопасность потоков).Выбранный ответ - это своего рода обходной путь, поэтому я добавляю свой собственный обходной путь.
Мое решение заключалось в том, чтобы просмотреть все доступные коллекции в пространстве имен System.Collections.Concurrent, чтобы найти ту, в которой было бы тривиально удалить все элементы из коллекции.
У класса ConcurrentStack есть метод Clear (), который удаляет все элементы из коллекции. Фактически, это единственная коллекция в пространстве имен (в настоящее время), которая это делает. Да,
Push(T element)
вместо этого придетсяAdd(T element)
, но, честно говоря, это стоит сэкономленного времени.источник
ConcurrentBag
? Я не вижу никаких собственных свойств или методов для этого. ЭтоContains
не считается. Это метод расширения для общихIEnumerable
s, и он совсем не эффективен.В духе обходных путей ..
ConcurrentDictionary<T, bool>
имеет атомарный Clear, но также позволяет быстро проверить, существует ли ключ. «Быстро», конечно, относительный термин, но в зависимости от вашего использования он может быть быстрее, чем перечисление большого стека.источник
Начиная с .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0, есть
Clear()
методConcurrentBag<T>
. См. ConcurrentBag.Clear .источник
int cnt = _queue.Count; for (; cnt > 0; cnt--) { _queue.TryDequeue(out img); }
Он не попадает в бесконечный цикл, а очищает содержимое настоящего времени.
источник