Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从ConcurrentBag中删除所有项目?_C#_Concurrency - Fatal编程技术网

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

C# 如何从ConcurrentBag中删除所有项目?,c#,concurrency,C#,Concurrency,如何清除ConcurrentBag?它没有任何类似于Clear或RemoveAll..的方法,尽管由于潜在的竞争条件,它可能无法完全清除,但这就足够了: while (!myBag.IsEmpty) { myBag.TryTake(out T _); } 2017年3月10日更新:正如@Lou正确指出的,分配是原子的。在这种情况下,ConcurrentBag的创建将不是原子的,但将该引用放入变量将是原子的-因此锁定或联锁。不严格要求围绕它进行交换 进一步阅读: 您可以始终锁定对包

如何清除
ConcurrentBag
?它没有任何类似于
Clear
RemoveAll
..

的方法,尽管由于潜在的竞争条件,它可能无法完全清除,但这就足够了:

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

2017年3月10日更新:正如@Lou正确指出的,分配是原子的。在这种情况下,
ConcurrentBag
的创建将不是原子的,但将该引用放入变量将是原子的-因此锁定或
联锁。不严格要求围绕它进行交换

进一步阅读:


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

lock (something)
{
    bag = new ConcurrentBag();
}
或者正如卢卡索伊德所指出的:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
var newBag=newconcurrentbag();
联锁交换(参考袋、新袋);
然而,这是一种简单的内容装箱方法,它假设每当一个项目需要访问时,它也会得到锁-这可能会很昂贵,并且可能会否定进入
ConcurrentBag
本身的性能调整


如果您知道此时没有其他人会访问该包,请仔细阅读,不要锁定:-)

选择的答案是一种变通方法,因此我添加了自己的变通方法

我的解决方案是查看名称空间中的所有可用集合,找到一个可以从集合中清除所有元素的集合


该类有一个从集合中删除所有元素的方法。事实上,它是命名空间中(当前)唯一一个这样做的集合。是的,您必须
推(T元素)
而不是
添加(T元素)
,但坦率地说,这是值得节省时间的

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

从.NET Core 2.0/.NET Standard 2.1/.NET Framework 5.0开始,在
ConcurrentBag上有一个
Clear()
方法。请参阅:


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

不过,这两个集合之间还有许多其他重要的区别。例如,如果您需要确定某个给定的项目是否在集合中,那么用一个包,而不是一堆,它既简单又有效。@Servy:是的,但仍然如此。不,事实上,我确实开始写一份赞成/反对列表,但这取决于你的要求。例如,并发集合适合多线程访问,但它们都不允许您索引到集合中,这可能会阻止您使用它们。这个问题是关于清除并发包的(这就是为什么我会遇到它),我的要求是使用线程安全性对集合进行琐碎的清除。我的答案是切换集合。我也使用并发堆栈而不是包。奇怪的是,堆栈中有明确的和袋不。bag的主要用途是存储值、检查是否存在并删除所有或单个值。所以并发堆栈类似于“一个位受限的实际并发包”。@Servy您如何有效地确定给定项是否包含在
ConcurrentBag
中?我看不到任何本机属性或方法可以这样做。
包含的
不计算在内。它是泛型
IEnumerable
s的一种扩展方法,但效率很低。这绝对不是原子的。因此,我想不应该在ConcurrentBag上添加作为扩展方法,因为所有其他方法都是在原子访问的假设下使用的,除了它是空的之外,不能因为其他原因尝试获取失败吗?这是非常危险的。如果另一个进程持续添加项目,这可能会保持繁忙状态。来自@Adam Houldsworth+我的评论的答案更好。如果这是一个危险的解决方案,为什么它仍然是被接受的答案?你可能想读一下这篇文章,这不是一个更好的解决方案,只要在你消费包的任何地方复制一份包的参考资料,那么你就可以不受惩罚地只做
bag=new
?@chrismaric是的,如果你可以避免共享数据,那么你就没有这些问题了。然而,这个问题没有太多的背景。
互锁。交换
可能比锁好。
互锁。交换
在交换时,如果另一个线程添加到包中,如何工作?
Add
是否在
Exchange
过程中被锁定?在.NET中,分配是原子的,锁和
都是互锁的。Exchange
在这里是冗余的(并且不提供线程安全)。很好!这应被视为为为此类实例选择的容器类型。ConcurrentStack类似。
int cnt = _queue.Count;
for (; cnt > 0; cnt--)
{
     _queue.TryDequeue(out img);
}