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

Paw*_*anS 69 c# concurrency

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

Ada*_*rth 58

更新10/03/2017:正如@Lou正确指出的那样,赋值是原子的.在这种情况下,创建ConcurrentBag不会是原子的,但将该引用放入变量是原子的 - 因此Interlocked.Exchange不严格要求锁定或围绕它.

进一步阅读:

引用赋值是原子的,为什么需要Interlocked.Exchange(ref Object,Object)?

参考分配线程安全吗?


您始终可以锁定对包本身的访问权限并创建它的新实例.如果没有其他东西可以保留在GC中,那么袋子中的物品将是合格的:

lock (something)
{
    bag = new ConcurrentBag();
}
Run Code Online (Sandbox Code Playgroud)

或者正如Lukazoid所指出的那样:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Run Code Online (Sandbox Code Playgroud)

然而,这样就可以轻松地对内容进行分区,这假设每当项目需要访问时它也会获得锁定 - 这可能是昂贵的,并且可能会抵消已经进入ConcurrentBag自身的性能调整.

如果你知道此时没有其他任何东西可以进入行李,那就不要锁定它并且不要锁定:-)

  • `Interlocked.Exchange`可能比锁更好 (10认同)
  • 如果另一个线程在交换时添加到包中,`Interlocked.Exchange`如何工作?那个`Add`在`Exchange`期间被锁定了吗? (5认同)
  • .NET 中的赋值是原子的,锁和“Interlocked.Exchange”在这里都是多余的(并且不提供线程安全)。 (2认同)

Dan*_*ite 36

T someItem;
while (!myBag.IsEmpty) 
{
   myBag.TryTake(out someItem);
}
Run Code Online (Sandbox Code Playgroud)

  • 这绝对不是原子的.因此,我不应该在ConcurrentBag上添加扩展方法,因为所有其他方法都是在假设原子访问的情况下使用的. (22认同)
  • 这是非常危险的.如果另一个过程是不断添加项目,这可能仍然很忙. (18认同)
  • @Adam Houldsworth的回答+我的评论更好. (3认同)

小智 21

选择的答案是一种解决方法,所以我正在添加自己的解决方法.

我的解决方案是查看System.Collections.Concurrent命名空间中的所有可用集合,以找到清除集合中所有元素的简单方法.

ConcurrentStack类有一个清除()方法,该方法从集合中删除所有元素.实际上,它是命名空间(当前)中唯一的集合.是的,你必须Push(T element)代替Add(T element),但坦率地说,值得节省时间.

  • 不过,他的收藏之间还有很多其他重要的区别。例如,如果您需要确定给定的项目是否在集合中,则使用 Bag 既简单又高效,但使用 Stack 则不然。 (2认同)
  • 我也使用并发堆栈而不是包。奇怪的是 stack 有 Clear 而 Bag 没有。bag 的主要目的是存储值,检查存在和删除全部或单个。所以并发堆栈变得类似于“有点有限的真实并发包”。 (2认同)

gor*_*gor 8

您可以在循环中逐个删除对象:

object result;
while (bag.TryTake(out result));
Run Code Online (Sandbox Code Playgroud)

请注意,在循环之后bag不保证是空的,因为可以在循环完成之后和不同线程的下一个语句之前添加项.

  • 这是错误的,因为接受的答案是错误的. (3认同)

ola*_*ker 8

从 .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 开始,Clear()ConcurrentBag<T>. 请参阅:ConcurrentBag.Clear


Old*_*eve 7

本着解决方法的精神...... ConcurrentDictionary<T, bool>有一个原子清除,但也允许你快速检查一个键是否存在."快速"当然是一个相对术语,但根据您的使用情况,它可能比枚举大型堆栈更快.