在 C# 中尝试从 ConcurrentDictionary 中删除键值对
TryRemove a key-value pair from ConcurrentDictionary in C#
我的情况是我想要一个像这样的 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;
}
}
我会做这样的事情
bool success = false;
lock(lockForDictionary)
{
string val;
if (dict.TryGetValue(keyTryToRemove, out val) && val == valTryToRemove)
{
dict.Remove(keyTryToRemove);
success = true;
}
}
因为 ConcurrentDictionary<TKey, TValue>
class implements (although explicitly) IDictionary<TKey, TValue>
, thus ICollection<KeyValuePair<TKey, TValue>>
, you can simply cast it to the later and use Remove
方法是这样的:
bool success = ((ICollection<KeyValuePair<TKey, TValue>>)dict).Remove(
new KeyValuePair<TKey, TValue>(key, value));
implementation 在内部使用与 public TryRemove
方法相同的线程安全方法(额外传递要检查的值)- 完全应该是这样。
编辑: 一般来说,所讨论的方法可用于实现 IDictionary<TKey, TValue>
(或更准确地说 ICollection<KeyValuePair<TKey, TValue>>
)的任何类型,例如 Dictionary
、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));
}
}
所以示例代码变得简单:
bool success = dict.TryRemove(key, value);
下面是一段代码,简化了一些步骤。
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。这些方法有帮助吗?
我的情况是我想要一个像这样的 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;
}
}
我会做这样的事情
bool success = false;
lock(lockForDictionary)
{
string val;
if (dict.TryGetValue(keyTryToRemove, out val) && val == valTryToRemove)
{
dict.Remove(keyTryToRemove);
success = true;
}
}
因为 ConcurrentDictionary<TKey, TValue>
class implements (although explicitly) IDictionary<TKey, TValue>
, thus ICollection<KeyValuePair<TKey, TValue>>
, you can simply cast it to the later and use Remove
方法是这样的:
bool success = ((ICollection<KeyValuePair<TKey, TValue>>)dict).Remove(
new KeyValuePair<TKey, TValue>(key, value));
implementation 在内部使用与 public TryRemove
方法相同的线程安全方法(额外传递要检查的值)- 完全应该是这样。
编辑: 一般来说,所讨论的方法可用于实现 IDictionary<TKey, TValue>
(或更准确地说 ICollection<KeyValuePair<TKey, TValue>>
)的任何类型,例如 Dictionary
、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));
}
}
所以示例代码变得简单:
bool success = dict.TryRemove(key, value);
下面是一段代码,简化了一些步骤。
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。这些方法有帮助吗?