ConcurrentDictionary:如果值不存在或条件失败,如何添加?

时间:2017-07-15 15:05:04

标签: c# concurrency

我正在尝试实现ConcurrentDictionary的扩展方法,如果key存在,它将从字典中获取值。如果密钥不存在或条件(在predicate中)失败,则会尝试通过调用valueFactory来获取值。以下是我写的方法。

public static TValue ConditionalGetOrAdd<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> dictionary,
    TKey key,
    Func<TValue, bool> predicate,
    Func<TKey, TValue> valueFactory)
{
    TValue value = dictionary.GetOrAdd(key, valueFactory);

    if (!predicate(value))
    {
        value = valueFactory(key);
        dictionary[key] = value;
    }

    return value;
}

这里有两个问题。如果valueFactory返回false,我可以拨打predicate两次。这将是多余的操作。另外,整个方法不是原子的。如果一个线程在if块内,则另一个线程不会等待它完成,然后再调用GetOrAddpredicate

是否可以在不锁定整个字典的情况下完成此操作?在我的情况下,valueFactory代价很高(在内部发出HTTP请求),而predicate非常便宜。如果您有解决方案,请告诉我。我可以修改整个方法,如果它有用的话。

1 个答案:

答案 0 :(得分:1)

谢谢,@ john的建议。 AddOrUpdate应该对我有用。添加下面的新方法体:

return dictionary.AddOrUpdate(
     key,
     valueFactory,
     (k, v) => predicate(v) ? v : valueFactory(k));

我会将此作为一种扩展方法,而不是直接在调用者中调用AddOrUpdate,因为它允许我在上面两个地方重用valueFactory委托。