2009-12-16 11 views
5

Por qué SynchronizedCollection<T> no adquiera un bloqueo en SyncObj en la implementación explícita de IEnumerable.GetEnumerator()SynchronizedCollection <T> no se bloquea en IEnumerable.GetEnumerator()

IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.items.GetEnumerator(); 
    } 

aplicación implícito no adquirir un bloqueo en SyncOb (verificado por el reflector).

Podría haber un problema durante el ciclo foreach en esta colección. ¿Un hilo podría haber adquirido un bloqueo y el otro podría intentar leerlo utilizando foreach?

Respuesta

1

La modificación de la colección mientras alguien está usando un iterador es una infracción de concurrencia de todos modos.

¿Cuál sería su alternativa? ¿Bloquea la colección cuando se adquiere el iterador y no lo desbloquea hasta que se destruye el iterador?

1

Voy a seguir adelante y decir que esto podría ser un error (ed: o al menos una incoherencia) en la implementación. El reflector muestra exactamente lo que está viendo, que cada otra implementación explícita llama al bloqueo en el SyncRoot dado, excepto en el IEnumerable.GetEnumerator().

Quizás deba enviar un ticket al Microsoft Connect.

Creo que la razón de la GetEnumerator() método implícito llama lock se debe a List<T>.GetEnumerator() crea un nuevo Enumerator<T> que se basa en el campo privado _version en la lista. Aunque estoy de acuerdo con los otros carteles, no veo el uso en el bloqueo de la llamada GetEnumerator(), pero dado que el constructor de Enumerator<T> se basa en campos que no son seguros para los hilos, sería lógico bloquearlo. O al menos seguir siendo coherente con las implementaciones implícitas.

4

Porque no hay forma de que la clase sepa cuando el código del cliente se completa con el iterador. Este es uno de los motivos por los que los documentos de MSDN Library en las clases System.Collection siempre advierten que iterar una colección no es seguro para subprocesos.

Aunque parecían haberse olvidado de mencionar eso en el artículo para SynchronizedCollection. La ironía ...

+1

Creo que a lo que se refiere es al hecho de que la implementación implícita de GetEnumerator() sí llama al bloqueo. – user7116

+0

De hecho lo hace. Tonto, no hay nada que deba ser bloqueado. La referencia de la lista interna no puede cambiar, solo su contenido. El iterador solo almacena la referencia de la lista. –

+0

Creo que debería hacerlo porque una llamada a 'GetEnumerator()' eventualmente crea un 'Enumerator ' nuevo que se basa en el campo 'List ._version'. – user7116

Cuestiones relacionadas