如何清除ConcurrentBag
?它没有任何方法,如Clear
或RemoveAll
...
答案 0 :(得分:55)
更新10/03/2017:正如@Lou正确指出的那样,赋值是原子的。在这种情况下,ConcurrentBag
的创建不是原子的,但是将该引用放入变量中将是原子的 - 因此不严格要求锁定或围绕它Interlocked.Exchange
。
进一步阅读:
reference assignment is atomic so why is Interlocked.Exchange(ref Object, Object) needed?
Is a reference assignment threadsafe?
您始终可以锁定对行李本身的访问权限并创建它的新实例。如果没有其他东西可以保留在GC中,那么袋子中的物品将是合格的:
lock (something)
{
bag = new ConcurrentBag();
}
或者Lukazoid指出:
var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
简单地将内容分区的方法,然而,这假设每当一个项目想要访问时它也会获得锁定 - 这可能是昂贵的并且可能会否定已进入ConcurrentBag
本身的性能调整。
如果你知道此时没有其他任何东西可以进入行李,那就不要锁定它并且不要锁定: - )
答案 1 :(得分:32)
T someItem;
while (!myBag.IsEmpty)
{
myBag.TryTake(out someItem);
}
答案 2 :(得分:18)
选择的答案很好,是一种解决方法,所以我正在添加自己的解决方法。
我的解决方案是查看System.Collections.Concurrent命名空间中的所有可用集合,找到一个清除集合中所有元素的简单集合。
ConcurrentStack类有一个Clear()方法,可以删除集合中的所有元素。实际上,它是命名空间(当前)中唯一的集合。是的,您必须Push(T element)
而不是Add(T element)
,但坦率地说,值得节省时间。
答案 3 :(得分:9)
您可以在循环中逐个删除对象:
object result;
while (bag.TryTake(out result));
请注意,在此循环后,bag不保证为空,因为可以在循环结束后和不同线程的下一个语句之前添加项目。
答案 4 :(得分:6)
本着解决方法的精神。ConcurrentDictionary<T, bool>
具有原子清除功能,但也允许您快速检查密钥是否存在。 “快速”当然是一个相对术语,但根据您的使用情况,它可能比枚举大型堆栈更快。
答案 5 :(得分:4)
从.NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0开始,Clear()
上有一个ConcurrentBag<T>
方法。参见:ConcurrentBag.Clear。
答案 6 :(得分:-2)
int cnt = _queue.Count;
for (; cnt > 0; cnt--)
{
_queue.TryDequeue(out img);
}
它不会陷入无限循环,并清除当前时间的内容。