2012-01-24 8 views
6

que han declarado un diccionario de dicionary:Volviendo un diccionario en C# en un entorno multi-hilo

Dictionary<String, Dictionary<String, String>> values; 

tengo un captador de conseguir un diccionario a un índice específico:

public Dictionary<String,String> get(String idx) 
{ 
    lock (_lock) 
    { 
     return values[moduleName]; 
    } 
} 

Como se puede ver que estoy trabajando en un entorno multihilo. Mi pregunta es ¿tengo que devolver una copia de mi diccionario con el fin de ser seguro para subprocesos como esto:

public Dictionary<String,String> get(String idx) 
{ 
    lock (_lock) 
    { 
     return new Dictionary<string, string>(values[moduleName]); 
    } 
} 

Si yo no voy a la clase que llama al comprador recibir una copia (por lo que si elimino este diccionario de mi Dictionary<String, Dictionary<String, String>> ¿seguirá funcionando?

Saludos,

Thierry.

+2

Probablemente no deba devolver el diccionario, pero si lo hace, entonces sí, necesita hacer una copia mientras está dentro de un monitor. ¿Puedes describir cuál debería ser el propósito de esta construcción? – Groo

+0

O utilice un [diccionario seguro para subprocesos] (http://msdn.microsoft.com/en-us/library/dd287191.aspx) –

+0

Gracias por su respuesta. –

Respuesta

4

Si realmente necesita devolver el diccionario en sí, necesitará reglas sobre cómo se enganchan los hilos (quebradizo, ¿y si hay un caso que no funciona?), Utilícelo en una lectura única forma (el diccionario es seguro para subprocesos solo para lectura, pero tenga en cuenta que esto supone que el código privado para la clase ya no está escribiéndole tampoco), use un diccionario seguro para subprocesos (ConcurrentDictionary usa bloqueo a rayas, mi ThreadSafeDictionary utiliza enfoques sin bloqueo, y hay diferentes escenarios donde uno supera al otro), o hace una copia como usted sugiere.

Sin embargo, aunque exponga un método para recuperar o establecer la última cadena encontrada por las dos teclas, enumerar las claves de segundo nivel encontradas por una tecla, etc., entonces no solo podrá controlar la bloqueo hecho en un solo lugar, pero tiene otras ventajas en la limpieza de la interfaz y en la liberación de la implementación desde la interfaz (por ejemplo, puede pasar del bloqueo al uso de un diccionario seguro para subprocesos, o viceversa, sin afectar el código de llamada))

2

Si no devuelve una copia, la persona que llama podrá cambiar el diccionario, pero esto no es un problema de seguridad de la secuencia.

También hay un problema de seguridad de subprocesos porque no expone ningún bloqueo para sincronizar escrituras y lecturas. Por ejemplo, su hilo de escritor puede agregar/eliminar un valor mientras el hilo lector está trabajando en la misma instancia.

Sí, tiene que devolver una copia.

+0

Simplemente podría documentar que las personas que usan el diccionario tienen que bloquearlo en algún lugar. – CodingBarfield

+0

Gracias por su respuesta, en mi caso tanto la persona que llama como la clase contenedora pueden acceder a los valores del diccionario devuelto, así que tendré que buscar una copia o un documento simultáneo. –

+0

@CodingBarfield Sí, pero debe exponer el objeto de sincronización de sincronismo que está utilizando para llenar el diccionario para que todos bloqueen el mismo objeto. No se recomienda bloquear el diccionario en sí, pero es otro tema. – Guillaume

6

Dictionary<> no es Thread-safe, pero ConncurrentDictionary<> es.

La clase que llama al captador recibe una referencia, lo que significa que seguirá allí si la quita del values -Diccionario ya que el GC no lo limpia mientras tenga una referencia en alguna parte, simplemente no puede conseguirlo con el getter más.

Básicamente eso significa que tienes dos posibilidades cuando se utiliza Dictionary<>:

  • planilla copia: Mala idea, ya que si se cambia la configuración que tiene dos configuraciones diferentes en su aplicación "vivo"
  • bloquear la instancia: esto haría más seguro para subprocesos, pero luego utilizar ConcurrentDictionary<> ya que hace exactamente eso para usted
+0

Y recuerda. Los artículos recuperados de ConcurrentDictionary no se guardan automáticamente. – CodingBarfield

+0

Gracias por su respuesta, me ayudó a entender mejor. –

Cuestiones relacionadas