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


Answers:


37

尽管由于潜在的比赛条件可能无法完全清除,但这已足够:

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

23
这绝对不是原子的。我猜应该不应该作为ConcurrentBag的扩展方法添加,因为所有其他方法都是在假设原子访问的情况下使用的。
阿努帕姆

另外,TryTake除了为空之外,是否还会由于其他原因而失败?
BrainSlugs83 2014年

21
这非常危险,如果另一个进程连续添加项目,可能会很忙。
IvoTops 2014年

4
@Adam Houldsworth +我的评论的答案更好。
克里斯·马里西奇

1
如果这是一个危险的解决方案,为什么仍然接受答案?
巴里斯Akkurt

65

更新10/03/2017:正如@Lou正确指出的那样,分配是原子的。在这种情况下,创建方法ConcurrentBag不会是原子的,但是将引用放入变量中将是原子的-因此,Interlocked.Exchange严格要求不对其进行锁定或锁定。

一些进一步的阅读:

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

参考分配是线程安全的吗?


您可以始终锁定对包本身的访问并创建它的新实例。如果没有其他东西抓住,则袋子中的物品将可识别为GC:

lock (something)
{
    bag = new ConcurrentBag();
}

或如Lukazoid所指出:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);

装箱内容的简便方法是,这假设,只要某项要访问,它也将获得锁定-这可能很昂贵,并且可能会抵消性能调整的影响。 ConcurrentBag

如果您知道此时没有其他东西可以进入该包,请翼翼并祈祷,不要锁定:-)


只是在您使用袋子的任何地方都带上袋子参考的副本,这是更好的解决方案,然后您可以bag = new不受惩罚地做吗?
克里斯·马里西奇

1
@ChrisMarisic是的,如果您完全可以避免共享数据,那么您就摆脱了这些问题。但是,这个问题没有太多的上下文。
亚当·霍兹沃思

10
Interlocked.Exchange可能比锁更好
Lukazoid

5
Interlocked.Exchange交换时如果另外一个线程添加到包中,该如何工作?那Add会在期间锁定Exchange吗?
布兰登2015年

2
赋值在.NET中是原子的,在Interlocked.Exchange这里锁和锁都是多余的(并且不提供线程安全性)。
Lou

24

选定的答案是一种解决方法,所以我要添加自己的解决方法。

我的解决方案是查看System.Collections.Concurrent命名空间中所有可用的集合,以查找从集合中清除所有元素的琐碎工作。

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


1
他的收藏之间还有许多其他重要区别。例如,如果您需要确定给定项目是否在集合中,那么使用Bag(袋)而不是Stack(堆栈)既简单又有效。
Servy 2013年

@Servy:是的,但是还是。不,实际上,我确实开始编写赞成/反对名单,但这实际上取决于您的要求。例如,并发集合非常适合多线程访问,但是它们都不允许您索引集合,这可能会阻止您使用它们。问题特别是关于清理并发包(这就是我遇到它的原因),而我的要求是通过线程安全来轻松清理集合。我的答案是更换收藏。

1
我也使用并发堆栈而不是bag。奇怪的是,堆栈没有Clear和Bag。包的主要目的是存储值,检查是否存在并删除全部或单个。因此,并发堆栈变得类似于“有点有限的真正并发包”。
Maxim

@Servy您如何有效确定给定项目是否包含在中ConcurrentBag?我看不到任何本机属性或方法。在Contains不计。它是泛型IEnumerables的扩展方法,它几乎没有效率。
Theodor Zoulias

9

本着变通办法的精神..ConcurrentDictionary<T, bool>具有原子清除功能,但是还允许您快速检查是否存在密钥。当然,“快速”是一个相对术语,但是根据您的使用情况,它可能比枚举大型堆栈要快。


好东西!这应被视为为此类实例选择的容器类型。ConcurrentStack同样。
延迟

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.