Si este diccionario rara vez se escribe y se lee con frecuencia, a menudo empleo el doble bloqueo seguro reemplazando todo el diccionario en la escritura. Esto es particularmente efectivo si puede escribir por lotes juntos para que sean menos frecuentes.
Por ejemplo, esta es una versión reducida de un método que usamos que intenta obtener un objeto de esquema asociado con un tipo, y si no puede, entonces sigue adelante y crea objetos de esquema para todos los tipos que se encuentra en el mismo conjunto como el tipo especificado para minimizar el número de veces que el diccionario entero tiene que ser copiado:
public static Schema GetSchema(Type type)
{
if (_schemaLookup.TryGetValue(type, out Schema schema))
return schema;
lock (_syncRoot) {
if (_schemaLookup.TryGetValue(type, out schema))
return schema;
var newLookup = new Dictionary<Type, Schema>(_schemaLookup);
foreach (var t in type.Assembly.GetTypes()) {
var newSchema = new Schema(t);
newLookup.Add(t, newSchema);
}
_schemaLookup = newLookup;
return _schemaLookup[type];
}
}
Así el diccionario, en este caso se reconstruirán, como máximo, tantas veces como hay asambleas con tipos que necesitan esquemas. Durante el resto de la vida útil de la aplicación, los accesos al diccionario estarán libres de bloqueos.La copia del diccionario se convierte en un costo de inicialización por única vez del ensamblaje. El intercambio de diccionario es seguro para subprocesos porque las escrituras del puntero son atómicas, por lo que toda la referencia se conmuta a la vez.
Puede aplicar principios similares en otras situaciones también.
es posible que desee retirar ConcurrentDictionary. – chillitom
Solo un detalle pero probablemente quiera decir '! ContainsKey()' –
¿Ha encontrado problemas de eficiencia al bloquear todo el diccionario? – Nick