有没有办法将ConcurrentDictionary.TryUpdate与lambda表达式一起使用?

Ufu*_*arı 10 .net c# concurrency

我有一个简单的场景,我想更新现有项目的值.只有AddOrUpdate方法提供了一个委托,我可以在其中更新旧值.但是,如果密钥不存在,我不想添加任何内容.此外,TryUpdate方法没有重载,我可以获得旧值.有没有办法用当前的API做到这一点?

这是我正在寻找的签名:

bool TryUpdate(TKey key, Func<TValue,TValue> updateValueFactory)
Run Code Online (Sandbox Code Playgroud)

Jon*_*nna 17

你必须准备好循环并且可能Func多次调用(与使用它的重载相同GetOrAdd).这意味着如果Func有副作用,它将不会从外部看起来是原子的.真的,Funcs不应该有副作用,但它们总是有一些成本,所以重复调用的可能性不容忽视:

public static bool TryUpdate<TKey, TValue>(
  this ConcurrentDictionary<TKey, TValue> dict,
  TKey key,
  Func<TValue, TValue> updateFactory)
{
    TValue curValue;
    while(dict.TryGetValue(key, out curValue))
    {
        if(dict.TryUpdate(key, updateFactory(curValue), curValue))
            return true;
        // if we're looping either the key was removed by another thread,
        // or another thread changed the value, so we start again.
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

如上所述,因为它可以循环,如果没有副作用,它只是从外面观察到的原子Func.

(编辑:删除一个非常普遍使用的潜在捷径,并且可能会咬人尝试它的人).