如何从ConcurrentBag中删除所有项目?

时间:2011-03-21 12:01:01

标签: c# concurrency

如何清除ConcurrentBag?它没有任何方法,如ClearRemoveAll ...

7 个答案:

答案 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);
}

它不会陷入无限循环,并清除当前时间的内容。