使用ConcurrentDictionary.GetOrAdd时有没有办法判断是否成功找到某个值或者是否添加了该值?

问题描述 投票:0回答:2

我有一些代码,使用

GetOrAdd
中的
ConcurrentDictionary
函数将带有唯一密钥的值添加到持有者中。但是,我希望能够判断是否找到了值键(即从
true
返回的
TryGet
)或者是否必须添加它。

我在网上找不到任何表明这是可以实现的东西,所以如果有人有任何想法,那将会非常有帮助。

c# collections concurrency concurrentdictionary
2个回答
0
投票

不一致,不。如果该方法返回的值不是您提供的值,那么您就知道该键已经存在,但如果该键存在并且具有与您提供的值相同的值,则不会有任何区别。如果您想确切地知道,那么您必须首先测试密钥。听起来您最好的选择是先致电

ContainsKey
,然后再致电
GetOrAdd
。您可以将其包装到您自己的单个方法中,这样如果您需要它是原子的,就可以轻松重用和锁定字典。


0
投票

这是我的无锁尝试。如果在调用时没有这样的键,则

GetOrAdd
可以调用委托,但如果另一个线程获胜,最终可能会放弃返回。这个想法是在 lambda 内部创建一个新对象,然后将其与
GetOrAdd
返回的内容进行比较(如果它是作为“Add”启动的),以减少比较开销。它尚未被证明是可靠的,但对我来说看起来是原子的和高性能的。

我把它作为扩展:

public static class ConcurrentDictionaryExtensions
{
    public static bool TryGetOrAdd<TKey, TValue>(
        this ConcurrentDictionary<TKey, TValue> dictionary,
        TKey key,
        out TValue resultingValue) where TValue : class, new()
    {
        bool added = false;
        TValue newValue = null;

        resultingValue = dictionary.GetOrAdd(key, _ => {
            newValue = new TValue();
            added = true; // Indicate that a new object is being created.
            return newValue;
        });

        return added ? ReferenceEquals(resultingValue, newValue) : false;
    }
}

用途:

bool isNew = myDictionary.TryGetOrAdd(1, out var resultingValue);
© www.soinside.com 2019 - 2024. All rights reserved.