[英]How to remove all Items from ConcurrentBag?
如何清除ConcurrentBag
? 它沒有任何方法,如Clear
或RemoveAll
...
2017 年 3月 10 日更新:正如 @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
本身的性能調整。
如果您知道此時沒有其他東西可以進入袋子,請邊祈禱邊祈禱,不要鎖定:-)
盡管由於潛在的競爭條件可能無法完全清除,但這已經足夠了:
while (!myBag.IsEmpty)
{
myBag.TryTake(out T _);
}
選定的答案是一種解決方法,所以我添加了我自己的解決方法。
我的解決方案是查看System.Collections.Concurrent命名空間中的所有可用集合,以找到一個可以輕松清除集合中所有元素的集合。
ConcurrentStack類有一個Clear()方法,它從集合中刪除所有元素。 事實上,它是命名空間(當前)中唯一的集合。 是的,您必須使用Push(T element)
而不是Add(T element)
,但坦率地說,這值得節省時間。
本着變通辦法的精神.. ConcurrentDictionary<T, bool>
有一個原子清除,但也允許您快速檢查鍵是否存在。 “快速”當然是一個相對術語,但根據您的使用情況,它可能比枚舉大型堆棧更快。
您可以在循環中逐個刪除對象:
object result;
while (bag.TryTake(out result));
請注意,在循環之后bag不保證是空的,因為可以在循環完成之后和不同線程的下一個語句之前添加項。
從 .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 開始, ConcurrentBag<T>
上有一個Clear()
方法。 請參閱: ConcurrentBag.Clear 。
好吧,我一直認為讓底層框架完成工作會更好。 我只是將邏輯包裝在一個專用的 function 中,發布 function 調用,所有局部變量將在 GC 認為有必要時自動丟棄。
void MyMainFunction(){
DoWorkWithTheBag();
}
void DoWorkWithTheBag(){
var newBag = new ConcurrentBag();
.....
}
如果你想強制 GC,你也可以調用 GC.Collect。
int cnt = _queue.Count;
for (; cnt > 0; cnt--)
{
_queue.TryDequeue(out img);
}
它不會陷入無限循環,並清除當前時間的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.