thread safe example current concurrentbag concurrent c# concurrent-collections

c# - safe - ConcurrentDictionary AddOrUpdate



current dictionary c# (4)

Estoy intentando volver a escribir un código usando Dictionary para usar ConcurrentDictionary. He revisado algunos ejemplos, pero todavía tengo problemas para implementar la función AddOrUpdate. Este es el código 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;

No sé qué agregar para la porción de actualización:

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

Cualquier indicador sería apreciada.


Espero que no me haya perdido nada en tu pregunta, pero ¿por qué no solo así? Es más fácil, atómico y seguro para subprocesos (ver más abajo).

userDic[authUser.UserId] = sessionId;

Almacene un par de clave / valor en el diccionario incondicionalmente, sobrescribiendo cualquier valor para esa clave si la clave ya existe: use el colocador del indexador

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

El indexador es atómico, también. Si pasa una función en su lugar, podría no ser:

Todas estas operaciones son atómicas y son seguras para subprocesos con respecto a todas las demás operaciones en ConcurrentDictionary. La única advertencia a la atomicidad de cada operación es para aquellos que aceptan un delegado, a saber, AddOrUpdate y GetOrAdd. [...] estos delegados son invocados fuera de las cerraduras

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


Para aquellos que están interesados, actualmente estoy implementando un caso que es un gran ejemplo para usar el valor anterior de "oldValue" en lugar de forzar uno nuevo (personalmente no me gusta el término "oldValue" ya que no es antiguo cuando se creó hace unos pocos tics de procesador desde dentro de un hilo paralelo).

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


Terminé implementando un método de extensión:

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); } }


Func pasar un Func que devuelve el valor que se almacenará en el diccionario en caso de una actualización. Supongo que en su caso (ya que no distingue entre agregar y actualizar) esto sería:

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

Es decir, el Func siempre devuelve el ID de sesión, de modo que tanto Agregar como Actualizar establecen el mismo valor.

Por cierto: hay una muestra en la página de MSDN .