2009-11-14 14 views

Respuesta

11

La razón por la que no puede encontrarlo es porque era explicitly removed. Si es realmente lo que quiere hacer, use un SynchronizedCollection<T> o cree un objeto de sincronización dedicado. El mejor enfoque (en general) es crear un objeto de sincronización dedicado, como lo ilustra Winston.

El problema esencial con la propiedad SyncRoot es que proporciona una falsa sensación de seguridad: solo maneja un conjunto muy limitado de circunstancias. Los desarrolladores a menudo descuidan la sincronización de toda una operación lógica, suponiendo que el bloqueo en SyncRoot es suficiente.

Por lo general, desea evitar el bloqueo en un tipo (List<T> en este caso). Si, por ejemplo, tiene dos instancias de su tipo u otro tipo que también usa un candado en List<T>, todos competirían por un único bloqueo global. Realmente, lo que estás tratando de lograr es una sincronización adecuada para un solo objeto.

0

Echa un vistazo here ("Colecciones concurrentes en C#").

+0

bien sé que el código Lista theList; lock (theList.SyncRoot) {} pero el problema es que no puedo obtener el elemento SyncRoot para mostrar en mi colección – Karim

7

tienen que desechar la lista genérica a un ICollection así:

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... 
} 

Tenga en cuenta que esto sólo se sincroniza el acceso a los elementos de la lista genérica. Sí no sincroniza el acceso a la variable genérica de la lista, por ejemplo, myIntList. Si reemplaza myIntList con una nueva lista en algún momento, usar SyncRoot no será suficiente. En ese caso, recomendaría crear un objeto de sincronización específico que pueda usarse para ambos escenarios de sincronización.

10

¿Por qué desea bloquear el List<T> en lugar de su instancia específica de una lista?

A menudo se sugiere que el mejor método de bloqueo es bloquear un objeto privado creado únicamente para ese fin.

private readonly object myListLock = new object(); 

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

Para una gran guía para enhebrar en C#, vea este Free E-Book (Threading in C#) por Joe Albahari.

+0

No creo que quiera bloquear 'List '. Quiere bloquear su instancia 'List ' utilizando la propiedad ICollection.SyncRoot (http://msdn.microsoft.com/en-us/library/bb356596.aspx). –

+0

De hecho, eso es lo que dijo su mensaje. Pero el título me lleva a creer que estaba considerando bloquear en la lista como alternativa. –

+2

¿Por qué es mejor que bloquear la instancia de la lista? – foson

2

La respuesta es Sí, se puede utilizar una instancia de la lista como un objeto de sincronización:

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

lock(list) 
{ 
    // ... 
} 

Así que usted no tiene que utilizar la propiedad SyncRoot. Por otra parte, afirma que documentation

Para colecciones cuyos almacén subyacente no es públicamente disponible, el de ejecución previsto es devolver la instancia actual.

es decir, en algunos casos, la propiedad SyncRoot devuelve el objeto de recopilación.

Lea también this answer sobre SyncRoot.

FYI: Nunca he visto usos de SyncRoot en el código de producción. Entonces, sugiere que use la instancia de cualquier colección como un objeto de sincronización en lugar de su propiedad SyncRoot (siempre que la colección sea privada).

Cuestiones relacionadas