I have a ConcurrentBag of objects, and I want to do following over it:
- enumerate all items with a where filtering.
- for each item, check some properties, and based on the values, make some method call. After the method call, it's better to remove the item form the bag.
- modify some properties' value and save it to the bag.
So basically I need something like following:
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?
}
}
Of cause it should be done in a thread-safe way. I know that the enumeration over a ConcurrentBag is actually over a "snapshot" of the real bag, but how about with a where clause filter? Should I do a ToList to prevent it form making a new "snapshot"? Also if you want to modify one specific item, you just bag.TryTake(out item). But since I've already get the item in the enumeration, should I "take" it again?
Any explanation/comment/sample would be very much apricated.
Thank you.
CodePudding user response:
I recommend you just create a new list and, if the WHERE filter, add it to this new list. It would look something like this:
List<T> myNewList = new List<T>();
foreach (var item in myBag.Where(it => it.Property1 = true))
{
if (!item.Property2 = true)
{
myNewList.Add(item);
}
}
attention to " ! "
CodePudding user response:
I'll try to answer specific parts of your question without addressing the performance.
First off, the Where
method takes an IEnumerable<T>
as its first parameter and will itself iterate over the enumerable which will call GetEnumerator()
once so you will only take one snapshot of the underlying ConcurrentBag
.
Secondly the thread-safety of your code is not very clear, there may be some implicit guarantees in the rest of your code which are not specified. For example you have a ConcurrentBag
so your collection is thread-safe however you modify the items contained within that collection without any thread synchronisation. If there is other code that runs the same method or in another method that reads/modifies the items in the ConcurrentBag
concurrently then you may see data races.
Note that it is not necessary to call TryTake
if you already have a reference to the item as it will only return the same reference.