Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

317
Vistas
¿Se garantiza que ConcurrentDictionary.GetOrAdd() invoque valueFactoryMethod solo una vez por clave?

Problema: necesito implementar caché de objetos. El caché debe ser seguro para subprocesos y debe completar los valores a pedido (carga diferida). Los valores se recuperan a través del servicio web mediante Key (operación lenta). Así que he decidido usar ConcurrentDictionary y su método GetOrAdd() que tiene un método de fábrica de valores suponiendo que la operación es atómica y sincronizada. Desafortunadamente, encontré la siguiente declaración en el artículo de MSDN: Cómo: Agregar y quitar elementos de un diccionario concurrente :

Además, aunque todos los métodos de ConcurrentDictionary son seguros para subprocesos, no todos los métodos son atómicos, específicamente GetOrAdd y AddOrUpdate. El delegado de usuario que se pasa a estos métodos se invoca fuera del bloqueo interno del diccionario.

Bueno, eso es desafortunado, pero aún no responde mi respuesta por completo.

Pregunta: ¿Se invoca value factory solo una vez por tecla? En mi caso específico: ¿es posible que múltiples subprocesos que buscan la misma clave generen múltiples solicitudes al servicio web por el mismo valor?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Como ya han señalado otros, valueFactory puede invocarse más de una vez. Existe una solución común que mitiga este problema: haga que valueFactory devuelva una instancia de Lazy<T> . Aunque es posible que se creen varias instancias diferidas, el valor T real solo se creará cuando acceda a la propiedad Lazy<T>.Value .

Específicamente:

 // Lazy instance may be created multiple times, but only one will actually be used. // GetObjectFromRemoteServer will not be called here. var lazyObject = dict.GetOrAdd("key", key => new Lazy<MyObject>(() => GetObjectFromRemoteServer())); // Only here GetObjectFromRemoteServer() will be called. // The next calls will not go to the server var myObject = lazyObject.Value;

Este método se explica con más detalle en la publicación del blog de Reed Copsey

over 4 years ago · Santiago Trujillo Denunciar

0

¿Se invoca value factory solo una vez por tecla?

No, no lo es. Los documentos dicen :

Si llama a GetOrAdd simultáneamente en diferentes subprocesos, valueFactory puede invocarse varias veces , pero es posible que su par clave/valor no se agregue al diccionario para cada llamada.

over 4 years ago · Santiago Trujillo Denunciar

0

Echemos un vistazo al código fuente de GetOrAdd :

 public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) { if (key == null) throw new ArgumentNullException("key"); if (valueFactory == null) throw new ArgumentNullException("valueFactory"); TValue resultingValue; if (TryGetValue(key, out resultingValue)) { return resultingValue; } TryAddInternal(key, valueFactory(key), false, true, out resultingValue); return resultingValue; }

Desafortunadamente, en este caso, está claro que nada garantiza que no se llamará a valueFactory más de una vez, si dos invocaciones de GetOrAdd se ejecutan en paralelo.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda