我有一個 ConcurrentBag 物件,我想對其進行以下操作:
- 使用 where 過濾列舉所有專案。
- 對于每個專案,檢查一些屬性,并根據這些值進行一些方法呼叫。方法呼叫后,最好從包中取出專案。
- 修改一些屬性的值并將其保存到包中。
所以基本上我需要如下內容:
foreach (var item in myBag.Where(it => it.Property1 = true))
{
if (item.Property2 = true)
{
SomeMethodToReadTheItem(item);
//it's better to remove this item from the bag here, but
//there is a permeance hit, then just leave it.
}
else
{
item.Property3= "new value";
//now how do I save the item back to the bag?
}
}
當然,它應該以執行緒安全的方式完成。我知道對 ConcurrentBag 的列舉實際上是在真實包的“快照”上,但是使用 where 子句過濾器怎么樣?我應該做一個 ToList 來防止它形成一個新的“快照”嗎?另外,如果你想修改一個特定的專案,你只需 bag.TryTake(out item)。但是既然我已經得到了列舉中的專案,我應該再次“接受”它嗎?
任何解釋/評論/示例都會非常有用。
謝謝你。
uj5u.com熱心網友回復:
我將嘗試回答您問題的特定部分,而不會解決性能問題。
首先,該Where方法將 anIEnumerable<T>作為它的第一個引數,并將自身迭代呼叫GetEnumerator()一次的可列舉,因此您將只獲取底層ConcurrentBag.
其次,您的代碼的執行緒安全性不是很清楚,您的代碼的其余部分可能有一些未指定的隱式保證。例如ConcurrentBag,您的集合是執行緒安全的,但是您無需任何執行緒同步即可修改該集合中包含的專案。如果有其他代碼運行相同的方法或在另一個方法中同時讀取/修改專案,ConcurrentBag那么您可能會看到資料競爭。
請注意,TryTake如果您已經擁有對該專案的參考,則沒有必要呼叫,因為它只會回傳相同的參考。
uj5u.com熱心網友回復:
我建議你只創建一個新串列,如果 WHERE 過濾器,將它添加到這個新串列中。它看起來像這樣:
List<T> myNewList = new List<T>();
foreach (var item in myBag.Where(it => it.Property1))
{
if (!item.Property2)
{
myNewList.Add(item);
}
}
注意“!”
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/382696.html
