如何清除ConcurrentBag
?它没有像Clear
或RemoveAll
...这样的任何方法
Answers:
尽管由于潜在的比赛条件可能无法完全清除,但这已足够:
while (!myBag.IsEmpty)
{
myBag.TryTake(out T _);
}
更新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
不受惩罚地做吗?
Interlocked.Exchange
可能比锁更好
Interlocked.Exchange
交换时如果另外一个线程添加到包中,该如何工作?那Add
会在期间锁定Exchange
吗?
Interlocked.Exchange
这里锁和锁都是多余的(并且不提供线程安全性)。
选定的答案是一种解决方法,所以我要添加自己的解决方法。
我的解决方案是查看System.Collections.Concurrent命名空间中所有可用的集合,以查找从集合中清除所有元素的琐碎工作。
该ConcurrentStack类有一个清除()方法,该方法从集合中删除所有元素。实际上,它是名称空间中(当前)唯一的集合。是的,您必须Push(T element)
代替Add(T element)
,但是坦率地说,这值得您节省时间。
ConcurrentBag
?我看不到任何本机属性或方法。在Contains
不计。它是泛型IEnumerable
s的扩展方法,它几乎没有效率。
从.NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0开始,在上有一种Clear()
方法ConcurrentBag<T>
。请参阅:ConcurrentBag.Clear。