这样做会更好:
public void Test()
{
ConcurrentDictionary<int, string> dictionary = new ConcurrentDictionary<int, string>();
dictionary.TryAdd(0, "A");
dictionary.TryAdd(1, "B");
dictionary.TryAdd(2, "A");
dictionary.TryAdd(3, "D");
foreach (var item in dictionary)
{
string foundItem;
if (dictionary.TryGetValue(item.Key, out foundItem))
{
if (foundItem == "A")
{
if (dictionary.TryRemove(item.Key, out foundItem))
{
// Success
}
}
}
}
}
比这个?:
public void Test2()
{
ConcurrentDictionary<int, string> dictionary = new ConcurrentDictionary<int, string>();
dictionary.TryAdd(0, "A");
dictionary.TryAdd(1, "B");
dictionary.TryAdd(2, "A");
dictionary.TryAdd(3, "D");
foreach (var item in dictionary)
{
string foundItem;
if (item.Value == "A")
{
if (dictionary.TryRemove(item.Key, out foundItem))
{
// Success
}
}
}
}
此方法将由多个线程访问。
我的困惑是,每当我想删除某个项目时,我会尝试先将其删除,然后将其删除。但首先,我使用了foreach
循环,这意味着我已经获得了该项目。任何想法都将不胜感激。
答案 0 :(得分:4)
我认为第一种方法没有任何好处。我只是使用LINQ来查找项目:
foreach (var entry in dictionary.Where(e => e.Value == "A"))
{
string ignored;
// Do you actually need to check the return value?
dictionary.TryRemove(entry.Key, out ignored);
}
当然,如果另一个线程添加值为"A"
的新条目或更新现有条目(可能使值"A"
,可能需要考虑,您需要考虑要发生的事情。当你正在迭代时,值不是 - "A"
对你来说这个条目是否被删除了吗?它不能保证会发生什么。(迭代器不会拍摄快照,但不是保证完全返回最新数据。)
希望通过检查我之后调用的"A"
变量来检查您删除的值是否为ignored
。这真的取决于你的背景。当您有多个线程修改地图时,您需要认为任何事情都可能发生 - 在您的代码实际执行的操作中。
还有一个事实是你实际上不得不浏览整本字典......你在其他地方用钥匙查找吗?
答案 1 :(得分:0)
第二种方法听起来不错。如果你有多个线程试图删除该项,其中一些将在TryRemove中失败,但一个会成功,这应该是好的。