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
自身的性能调整.
如果你知道此时没有其他任何东西可以进入行李,那就不要锁定它并且不要锁定:-)
Dan*_*ite 36
T someItem;
while (!myBag.IsEmpty)
{
myBag.TryTake(out someItem);
}
Run Code Online (Sandbox Code Playgroud)
小智 21
选择的答案是一种解决方法,所以我正在添加自己的解决方法.
我的解决方案是查看System.Collections.Concurrent命名空间中的所有可用集合,以找到清除集合中所有元素的简单方法.
该ConcurrentStack类有一个清除()方法,该方法从集合中删除所有元素.实际上,它是命名空间(当前)中唯一的集合.是的,你必须Push(T element)
代替Add(T element)
,但坦率地说,值得节省时间.
您可以在循环中逐个删除对象:
object result;
while (bag.TryTake(out result));
Run Code Online (Sandbox Code Playgroud)
请注意,在循环之后bag不保证是空的,因为可以在循环完成之后和不同线程的下一个语句之前添加项.
从 .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 开始,Clear()
在ConcurrentBag<T>
. 请参阅:ConcurrentBag.Clear。
本着解决方法的精神...... ConcurrentDictionary<T, bool>
有一个原子清除,但也允许你快速检查一个键是否存在."快速"当然是一个相对术语,但根据您的使用情况,它可能比枚举大型堆栈更快.