我正在尝试实现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
块内,则另一个线程不会等待它完成,然后再调用GetOrAdd
或predicate
。
是否可以在不锁定整个字典的情况下完成此操作?在我的情况下,valueFactory
代价很高(在内部发出HTTP请求),而predicate
非常便宜。如果您有解决方案,请告诉我。我可以修改整个方法,如果它有用的话。
答案 0 :(得分:1)
谢谢,@ john的建议。 AddOrUpdate
应该对我有用。添加下面的新方法体:
return dictionary.AddOrUpdate(
key,
valueFactory,
(k, v) => predicate(v) ? v : valueFactory(k));
我会将此作为一种扩展方法,而不是直接在调用者中调用AddOrUpdate
,因为它允许我在上面两个地方重用valueFactory
委托。