2012-06-27 8 views
14

En lo que respecta a seguridad de subprocesos, ¿está bien hacerlo o debo utilizar una colección diferente?Parallel.ForEach en la lista <Object> Seguridad de subprocesos

 List<FileMemberEntity> fileInfo = getList(); 

     Parallel.ForEach(fileInfo, fileMember => 
     { 
       //Modify each fileMember 
     } 
+0

Se le recuerda preguntas singular. –

+1

¿Está modificando algo en su ciclo foreach? si no, entonces probablemente no haya preocupación por la seguridad del hilo. Si está modificando, deberá realizar un bloqueo – Didaxis

+0

¿Puedo usar una colección diferente y no necesito un bloqueo? –

Respuesta

22

Siempre y cuando solo modifique el contenido del elemento que se transfiere al método, no es necesario el bloqueo.

(por supuesto siempre que no hay referencia duplicado en la lista, es decir, dos referencias a la misma FileMemberEntity ejemplo.)

Si es necesario modificar la lista en sí, crear una copia que se puede repetir, y use un candado cuando modifique la lista:

List<FileMemberEntity> fileInfo = getList(); 

List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo); 
object sync = new Object(); 

Parallel.ForEach(copy, fileMember => { 
    // do something 
    lock (sync) { 
    // here you can add or remove items from the fileInfo list 
    } 
    // do something 
}); 
+0

El contenido es la colección .... no lo que está contenido en la colección correcta? –

+0

@MicahArmantrout: El contenido es el que está en la instancia 'FileMemberEntity' que se pasa como' fileMember' al método. – Guffa

+0

Entonces, ¿eso hará que todos los otros subprocesos se detengan hasta que salga de la cerradura o con Parallel.ForEach pasará el hilo a otro elemento en la lista? –

4

Estás seguro ya que estás leyendo. Simplemente no modifique la lista mientras itera sobre sus elementos.

+0

Estoy modificando los elementos en la colección –

+0

Eso está bien, siempre y cuando ya que no estás modificando la colección en sí. No puede reordenar elementos en él, ni puede agregar o eliminar elementos en él. – Henrik

+1

Entonces, si estoy actualizando los elementos de la lista, ¿no importa tanto como sea posible que no cambie la colección actual? –

1

Si no importa en qué orden se actúan los objetos FileMemberEntity, puede usar List<T> porque no está modificando la lista.

Si debe asegurarse algún tipo de pedido, puede usar OrderablePartitioner<T> como una clase base e implementar un esquema de partición apropiado. Por ejemplo, si el FileMemberEntity tiene algún tipo de categorización y debe procesar cada una de las categorías en algún orden específico, le conviene seguir esta ruta.

Hipotéticamente si tiene

Objeto 1 Categoría A

Objeto 2 Categoría A

Objeto 3 Categoría B

no hay ninguna garantía de que Object 2 Category A serán procesados ​​antes Object 3 Category B se procesa al iterar un List<T> usando Parallel.ForEach.

La documentación de MSDN a la que se vincula proporciona un ejemplo de cómo hacerlo.

+0

Estoy modificando la colección dentro del foreach –

+0

Si está modificando los objetos en la colección (en lugar de la colección en sí) eso está bien. –

+0

¡MUCHAS GRACIAS! –

2

Deberíamos usar menos objetos de bloqueo para hacerlo más rápido. Sólo objeto de bloqueo en diferentes temas locales de Parrallel.ForEach:

List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo); 
object sync = new Object(); 

Parallel.ForEach<FileMemberEntity, List<FileMemberEntity>>(
     copy, 
    () => { return new List<FileMemberEntity>(); }, 
     (itemInCopy, state, localList) => 
     { 
     // here you can add or remove items from the fileInfo list 
     localList.Add(itemInCopy); 
     return localList; 
     }, 
     (finalResult) => { lock (sync) copy.AddRange(finalResult); } 
); 

// do something 

Referencia: http://msdn.microsoft.com/en-gb/library/ff963547.aspx

Cuestiones relacionadas