What to add for the update portion in ConcurrentDictionary AddOrUpdate

You need to pass a Func which returns the value to be stored in the dictionary in case of an update. I guess in your case (since you don't distinguish between add and update) this would be:

var sessionId = a.Session.SessionID.ToString();
userDic.AddOrUpdate(
  authUser.UserId,
  sessionId,
  (key, oldValue) => sessionId);

I.e. the Func always returns the sessionId, so that both Add and Update set the same value.

BTW: there is a sample on the MSDN page.


I hope, that I did not miss anything in your question, but why not just like this? It is easier, atomic and thread-safe (see below).

userDic[authUser.UserId] = sessionId;

Store a key/value pair into the dictionary unconditionally, overwriting any value for that key if the key already exists: Use the indexer’s setter

(See: http://blogs.msdn.com/b/pfxteam/archive/2010/01/08/9945809.aspx)

The indexer is atomic, too. If you pass a function instead, it might not be:

All of these operations are atomic and are thread-safe with regards to all other operations on the ConcurrentDictionary. The only caveat to the atomicity of each operation is for those which accept a delegate, namely AddOrUpdate and GetOrAdd. [...] these delegates are invoked outside of the locks

See: http://blogs.msdn.com/b/pfxteam/archive/2010/01/08/9945809.aspx


I ended up implementing an extension method:

static class ExtensionMethods
{
    // Either Add or overwrite
    public static void AddOrUpdate<K, V>(this ConcurrentDictionary<K, V> dictionary, K key, V value)
    {
        dictionary.AddOrUpdate(key, value, (oldkey, oldvalue) => value);
    }
}

For those who are interested in, I am currently implementing a case which is a great example for using the "oldValue" aka existing value instead of forcing a new one (personally I don't like the term "oldValue" as it is not that old when it was created just a few processor ticks ago from within a parallel thread).

dictionaryCacheQueues.AddOrUpdate(
    uid,
    new ConcurrentQueue<T>(),
    (existingUid, existingValue) => existingValue
);