2010-08-04 50 views
42

Me gustaría utilizar la nueva función Parallel.ForEach para recorrer una tabla de datos y realizar acciones en cada fila. Estoy tratando de convertir el código de abajo:Parallel ForEach en DataTable

 foreach(DataRow drow in dt.Rows) 
     { 
      ... 
      Do Stuff 
      ... 
     } 

Para este código:

 System.Threading.Tasks.Parallel.ForEach(dt.Rows, drow => 
       { 
        ... 
        Do Stuff 
        ... 
       }); 

Cuando ejecuto el nuevo código me sale el error:

Los argumentos de tipo para el método del sistema ' .Threading.Tasks.Parallel.ForEach (System.Collections.Generic.IEnumerable, System.Action) 'no se puede deducir del uso. Intente especificar los argumentos de tipo explícitamente.

¿Cuál es la sintaxis correcta para esto?

Respuesta

89

DataTable.Rows devuelve un DataRowCollection que solo implementa IEnumerable, no IEnumerable<DataRow>. Utilice el método de extensión en AsEnumerable()DataTable (de DataTableExtensions) en su lugar:

Parallel.ForEach(dt.AsEnumerable(), drow => 
{ 
    ... 
    Do Stuff 
    ... 
}); 
+2

D'oh! ¡Golpe al golpe (por unos segundos)! – JaredReisinger

+0

¿Esta misma extensión estaría disponible para otras colecciones que implementen IEnumerable? como TreeNodeCollection? o tendré que crear esta extensión yo mismo? –

+0

@Scott: Tendría que escribirlo usted mismo, porque de lo contrario no va a saber qué tipo de 'IEnumerable ' devolver, si ve lo que quiero decir. –

7

Parallel.ForEach() espera que el primer argumento sea un IEnumerable <> Tipo. DataTable.Rows no lo es, pero puede convertirlo en uno con el método de extensión AsEnumerable(). Proveedores:

... Parallel.ForEach(dt.AsEnumerable(), drow => ... 
6

Esto es mejor que la respuesta aceptada, porque esto no es necesario hacer referencia a System.Data.DataSetExtensions:

Parallel.ForEach(dt.Rows.Cast<DataRow>(), dr => 

Para utilizar ParaCada con una colección no genérica, que puede utilizar la Método de extensión de conversión para convertir la colección en una colección genérica, como se muestra en este ejemplo.

+1

Pero tenga en cuenta esto , de [Cast docs] (https://msdn.microsoft.com/en-us/library/bb341406 (v = vs.110) .aspx): "Si un elemento no se puede convertir para escribir TResult, este método arrojará una excepción. Para obtener solo aquellos elementos que se pueden convertir para escribir TResult, use el método OfType en lugar de Cast (IEnumerable). " – ALEXintlsos

0

Tuve que modificar la respuesta de Jon Skeet para que funcione.

Parallel.ForEach(dt.AsEnumerable<DataRowType>(), drow => { 
    drow.SomeCol = ""; 
});