考虑下面的函数,它迭代通用List<T>
:项目,并改变匹配的项目,如果发现:用于修改ConcurrentBag中项目的可接受方法?
void UpdateList(ref List<clsMyClass> Items, int idToFind) {
foreach(var Item in Items) {
if (Item.ID == idToFind)
{
// modify the item
Item.SomeIntCounter++;
return;
}
}
}
现在,如果我想要做同样的事情,但使用一个线程安全的这个时候ConcurrentBag<T>
,这是一个可以接受的方法?...
void UpdateList(ref ConcurrentBag<clsMyClass> Items, int idToFind) {
clsMyClass Item;
bool found = false;
ConcurrentBag<clsMyClass> tempItems = new ConcurrentBag<clsMyClass>();
while(Items.Count > 0) {
if (Items.TryTake(out Item))
{
if (Item.ID == idToFind)
{
//modify the item
Item.SomeIntCounter++;
found = true;
}
tempItems.Add(Item);
if (found) break;
}
}
foreach(var tempItem in tempItems) Items.Add(tempItem);
}
这里的想法是,每个项目从ConcurrentBag删除并添加到一个临时直到匹配的项目被发现,改变,在此之后所有拆下的项目被重新添加到ConcurrentBag中。
这是一个明智的方式来修改线程安全的方式收集?
如果你的'ID'是唯一的,我会说'ConcurrentDictionary'更合适。不,你的第二种方法不是线程安全的,因为你没有使用任何锁,并且正在取物品,创建一个临时包等等,如果它们同时发生会造成问题。 – Maarten 2014-10-01 09:55:07
@Maarten谢谢 - 根据项目中使用的类别,ID未必是唯一的,因为未保存的条目的ID为0。另外,我认为Concurrent命名空间使用了它自己的内部锁定方法。我的函数也使用我认为是从ConcurrentBag:TryTake()中删除项目的线程安全方法? – Panjo 2014-10-01 10:14:01
如果你想要某个被称为*线程安全*的东西,那么**作为一个整体**的操作必须是线程安全的,并且使用线程安全的方法移除一个项目是不够的。 – Maarten 2014-10-01 10:34:10