2009-11-14 14 views

risposta

11

Il motivo per cui non riesci a trovarlo è perché era explicitly removed. Se è davvero quello che vuoi fare, usa un SynchronizedCollection<T> o crea un oggetto di sincronizzazione dedicato. L'approccio migliore (in generale) è creare un oggetto di sincronizzazione dedicato, come illustrato da Winston.

Il problema essenziale con la proprietà SyncRoot è che fornisce un falso senso di sicurezza - gestisce solo un insieme molto ristretto di circostanze. Gli sviluppatori spesso trascurano la sincronizzazione per un'intera operazione logica, presupponendo che il blocco su SyncRoot sia sufficiente.

Generalmente si desidera evitare il blocco su un tipo (List<T> in questo caso). Se, ad esempio, hai due istanze del tuo tipo, o un altro tipo dovresti utilizzare anche un blocco su List<T>, sarebbero tutti in competizione per un unico blocco globale. In realtà, quello che stai cercando di ottenere è la sincronizzazione corretta per un singolo oggetto.

0

Dai un'occhiata a here ("Raccolte simultanee in C#").

+0

beh so che il codice Elenco theList; lock (theList.SyncRoot) {} ma il problema è che non posso ottenere l'elemento SyncRoot da mostrare sulla mia collezione – Karim

7

si deve lanciare la lista generica a un ICollection come questo:

using System.Collection; // required for ICollection 
using System.Collection.Generic; 
List<int> myIntList = new List<int>(); 
lock (((ICollection)myIntList).SyncRoot) 
{ 
    // do your synchronized stuff here... 
} 

Tenete a mente che questo sincronizza solo l'accesso agli elementi della lista generica. È non sincronizzare l'accesso alla variabile di lista generica, ad esempio myIntList. Se si sostituisce myIntList con un nuovo elenco a un certo punto, utilizzare SyncRoot non sarà sufficiente. In tal caso, suggerirei di creare un oggetto di sincronizzazione specifico che può essere utilizzato per entrambi gli scenari di sincronizzazione.

10

Perché si desidera bloccare List<T> in contrasto con l'istanza specifica di un elenco?

Spesso si suggerisce che il metodo migliore per bloccare sia bloccare un oggetto privato creato esclusivamente per tale scopo.

private readonly object myListLock = new object(); 

// Everywhere you access myList 
lock(myListLock) 
{ 
// do stuff with myList 
} 

Per una grande guida per la filettatura in C#, vedere questo Free E-Book (Threading in C#) da Joe Albahari.

+0

Non penso che voglia bloccare 'Lista '. Vuole bloccare la sua istanza 'List ' utilizzando la proprietà ICollection.SyncRoot (http://msdn.microsoft.com/en-us/library/bb356596.aspx). –

+0

Infatti, questo è quello che ha detto il suo post. Ma il titolo mi porta a credere che stava prendendo in considerazione il blocco su List come alternativa. –

+2

Perché è meglio che bloccarsi sull'istanza della lista? – foson

2

La risposta è sì, è possibile utilizzare un'istanza della lista come un oggetto di sincronizzazione:

private readonly List<string> list = new List<string>(); 

lock(list) 
{ 
    // ... 
} 

Quindi non c'è bisogno di utilizzare la proprietà SyncRoot. Inoltre, afferma che documentation

Per le collezioni il cui negozio di fondo non è a disposizione del pubblico, l'attuazione prevista è quello di restituire l'istanza corrente.

, ad esempio in alcuni casi la proprietà SyncRoot restituisce l'oggetto stesso.

Leggere anche this answer su SyncRoot.

FYI: Non ho mai visto gli usi di SyncRoot nel codice di produzione. Quindi io suggerisco di utilizzare l'istanza di qualsiasi raccolta come oggetto di sincronizzazione invece della sua proprietà SyncRoot (purché la raccolta sia privata).

Problemi correlati