2012-01-24 10 views
6

ho dichiarato un dizionario di dicionary:Restituzione di un dizionario in C# in un ambiente multi-threaded

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

Ho un getter per ottenere un dizionario ad un indice specifico:

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

Come puoi vedere che sto lavorando in un ambiente multi-thread. La mia domanda è ho bisogno di restituire una copia del mio dizionario al fine di essere sicuri come questa discussione:

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

Se non sarà la classe che chiama il getter ricevere una copia (quindi se rimuovo questo dizionario dal mio Dictionary<String, Dictionary<String, String>> funzionerà ancora)?

Cheers,

Thierry.

+2

Probabilmente non si dovrebbe restituire il dizionario, ma se lo fai, allora sì, è necessario fare una copia mentre si è all'interno di un monitor. Puoi descrivere quale dovrebbe essere lo scopo di questo costrutto? – Groo

+0

Oppure utilizzare un [dizionario thread-safe] (http://msdn.microsoft.com/en-us/library/dd287191.aspx) –

+0

Grazie per la risposta. –

risposta

4

Se hai davvero bisogno di restituire il dizionario stesso, allora avrai bisogno di avere regole per il modo in cui i thread si bloccano su di esso (fragile, e se c'è un caso che non lo è?), Usarlo in un read- solo modo (dizionario è thread-safe per sola lettura, ma si noti che questo presuppone che il codice privato della classe non lo scriva più), usa un dizionario thread-safe (ConcurrentDictionary usa il blocco a strisce, my ThreadSafeDictionary usa approcci bloccati e ci sono diversi scenari in cui uno batte l'altro), o fai una copia come suggerisci tu.

In alternativa, se si espone un metodo per recuperare o impostare la stringa definitiva trovata dalle due chiavi, per enumerare le chiavi di secondo livello trovate da una chiave e così via, non solo si può controllare il blocco fatto in un unico posto, ma ha altri vantaggi nella pulizia dell'interfaccia e nella liberazione dell'implementazione dall'interfaccia (ad esempio, è possibile passare da un utilizzo basato su blocco a un dizionario thread-safe o viceversa senza influire sul codice chiamante).

2

Se non si restituisce una copia, il chiamante sarà in grado di cambiare il dizionario ma questo non è un problema di sicurezza dei thread.

C'è anche un problema di sicurezza del thread perché non esporre alcun blocco per sincronizzare scritture e letture. Ad esempio, il thread del writer può aggiungere/rimuovere un valore mentre il thread del lettore sta lavorando sulla stessa istanza.

Sì, è necessario restituire una copia.

+0

Si potrebbe semplicemente documentare che le persone che usano il dizionario devono bloccarlo da qualche parte. – CodingBarfield

+0

Grazie per la tua risposta, nel mio caso sia il chiamante che la classe contenente potrebbero accedere ai valori del dizionario restituito, quindi dovrò andare per una copia o un concurrentdictionary. –

+0

@CodingBarfield Sì, ma è necessario esporre l'oggetto Synclock che si sta utilizzando per popolare il dizionario in modo che tutti si blocchino sullo stesso oggetto. Il blocco del dizionario stesso non è raccomandato ma è un altro argomento. – Guillaume

6

Dictionary<> non è thread-safe, ma è ConncurrentDictionary<>.

La classe che chiama il getter riceve un riferimento, il che significa che sarà ancora presente se lo rimuovi dal codice values -Dictionary poiché il GC non lo pulisce finché hai un riferimento da qualche parte, non puoi prendilo più con il getter.

Basicaly che significa che hai due possibilità quando si utilizza Dictionary<>:

  • ritorno di una copia: cattiva idea, perché se si modifica la configurazione si hanno due diverse configurazioni della tua app "vivo"
  • bloccare l'istanza: questo renderebbe thread-safe, ma poi usare ConcurrentDictionary<> come fa esattamente questo per voi
+0

E ricorda. Gli elementi recuperati dal ConcurrentDictionary non sono automaticamente salvati nel thread! – CodingBarfield

+0

Grazie per la tua risposta, mi ha aiutato a capire meglio. –

Problemi correlati