我的场景是我想在ConcurrentDictionary
这样的方法。
bool TryRemove(TKey key, TValue value) {
// remove the value IF the value passed in == dictionary[key]
// return false if the key is not in the dictionary, or the value is not equal
}
有没有办法同时执行此操作?我很难找到这个场景的答案,尽管这似乎是一个常见的用例。
我可以做这样的事情,但如果我已经使用ConcurrentDictionary
,我想避免锁定。我还必须在其他地方GetOrAdd()
或AddOrUpdate()
来电。似乎应该有一个更好的方法ConcurrentDictionary
。
ConcurrentDictionary<int, string> dict = ...;
/// stuff
int keyTryToRemove = 1337;
string valTryToRemove = "someValue";
bool success = false;
lock(keyTryToRemove) {
string val;
if (dict.TryRemove(keyTryToRemove, out val)) {
if (val == valTryToRemove) {
success = true;
}
else { // reinsert value, UGLY!
dict[keyTryToRemove] = val;
success = false;
}
} else {
success = false;
}
}
答案 0 :(得分:5)
由于ConcurrentDictionary<TKey, TValue>
类实现了(虽然明确地)IDictionary<TKey, TValue>
,因此ICollection<KeyValuePair<TKey, TValue>>
,您可以简单地将其强制转换为后者并使用Remove
方法,如下所示:
bool success = ((ICollection<KeyValuePair<TKey, TValue>>)dict).Remove(
new KeyValuePair<TKey, TValue>(key, value));
implementation内部使用相同的线程安全方法(另外传递要检查的值)作为公共TryRemove
方法 - 完全应该如此。
修改:一般而言,相关方法可用于实施IDictionary<TKey, TValue>
(或更准确地说ICollection<KeyValuePair<TKey, TValue>>
)的任何类型,例如Dictionary
,{ {1}}等通过引入这样的自定义扩展方法:
ConcurrentDictionary
所以示例代码变得简单:
public static class Extensions
{
public static bool TryRemove<TKey, TValue>(this ICollection<KeyValuePair<TKey, TValue>> source, TKey key, TValue value)
{
return source.Remove(new KeyValuePair<TKey, TValue>(key, value));
}
}
答案 1 :(得分:0)
我做这样的事情
bool success = false;
lock(lockForDictionary)
{
string val;
if (dict.TryGetValue(keyTryToRemove, out val) && val == valTryToRemove)
{
dict.Remove(keyTryToRemove);
success = true;
}
}
答案 2 :(得分:0)
你可以在IDictionary
上编写类似这样的扩展方法。
public static class DictionaryHelper
{
public static bool TryRemoveIfValue<TKey, TValue>(this IDictionary<TKey,TValue> owner, TKey key, TValue value)
{
var success = false;
lock (owner)
{
TValue existingValue;
if (owner.TryGetValue(key, out existingValue))
{
if (value.Equals(existingValue))
{
owner.Remove(key);
success = true;
}
}
}
return success;
}
}
答案 3 :(得分:0)
下面是一段简化步骤的代码。
readonly object _locker = new object();
readonly ConcurrentDictionary<int, string> _dict = new ConcurrentDictionary<int, string>();
public bool TryRemove(int key, string value)
{
var success = false;
lock (_locker)
{
if (_dict.ContainsKey(key) && _dict[key] == value)
{
string val;
success = _dict.TryRemove(key, out val);
}
}
return success;
}
话虽如此,似乎目标本质上是非原子性的,这就是我们需要锁定的原因。重要的是要问,你的目标是什么,能否以原子方式表达目标。 ConcurrentDictionary的2个有用方法包括TryUpdate和AddOrUpdate。这些方法中的任何一种都有帮助吗?