web-dev-qa-db-fra.com

Quoi ajouter pour la partie mise à jour dans ConcurrentDictionary AddOrUpdate

J'essaye de réécrire du code en utilisant Dictionary pour utiliser ConcurrentDictionary. J'ai examiné quelques exemples, mais je ne parviens toujours pas à implémenter la fonction AddOrUpdate. Ceci est le code original:

    dynamic a = HttpContext;
    Dictionary<int, string> userDic = this.HttpContext.Application["UserSessionList"] as Dictionary<int, String>;

   if (userDic != null)
   {
      if (useDic.ContainsKey(authUser.UserId))
      {
        userDic.Remove(authUser.UserId);
      }
   }
  else
  {
     userDic = new Dictionary<int,string>();
  }
  userDic.Add(authUser.UserId, a.Session.SessionID.ToString());
  this.HttpContext.Application["UserDic"] = userDic;

Je ne sais pas quoi ajouter pour la partie mise à jour:

userDic.AddOrUpdate(authUser.UserId,
                    a.Session.SessionID.ToString(),
                    /*** what to add here? ***/);

Tous les pointeurs seraient appréciés.

98
user438331

Vous devez passer un Func qui renvoie la valeur à stocker dans le dictionnaire en cas de mise à jour. Je suppose que dans votre cas (puisque vous ne faites pas la distinction entre ajouter et mettre à jour), cela serait:

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

C'est à dire. le Func renvoie toujours l'ID de session, de sorte que les options Ajouter et Mettre à jour définissent la même valeur.

BTW: il y a un exemple sur la page MSDN .

204
M4N

J'espère que votre question ne m'a pas manqué, mais pourquoi pas comme ça? C'est plus facile, atomique et thread-safe (voir ci-dessous).

userDic[authUser.UserId] = sessionId;

Stockez une paire clé/valeur dans le dictionnaire sans condition, en écrasant toute valeur de cette clé si la clé existe déjà: utilisez le configurateur de l'indexeur.

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

L'indexeur est également atomique. Si vous passez une fonction à la place, il se peut que ce ne soit pas:

Toutes ces opérations sont atomiques et sont thread-safe par rapport à toutes les autres opérations sur le ConcurrentDictionary. La seule réserve à l'atomicité de chaque opération concerne ceux qui acceptent un délégué, à savoir AddOrUpdate et GetOrAdd. [...] ces délégués sont invoqués en dehors des serrures

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

57
Niklas Peter

J'ai fini par implémenter une méthode d'extension:

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);
    }
}
26
steve cook

Pour ceux qui sont intéressés, je suis en train de mettre en place un cas qui est un excellent exemple d'utilisation de la valeur "oldValue" ou de la valeur existante au lieu d'en forcer une nouvelle (personnellement, je n'aime pas le terme "oldValue", car ce n'est pas vieux quand il a été créé il ya quelques ticks de processeur dans un thread parallèle).

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