2010-08-04 21 views
42

Vorrei utilizzare la nuova funzione Parallel.ForEach per eseguire il ciclo di un datatable ed eseguire azioni su ogni riga. Sto cercando di convertire il codice qui sotto:Parallel ForEach on DataTable

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

a questo codice:

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

Quando eseguo il nuovo codice ottengo l'errore:

Il tipo di argomenti per il metodo 'Sistema .Threading.Tasks.Parallel.ForEach (System.Collections.Generic.IEnumerable, System.Action) 'non può essere dedotto dall'utilizzo. Prova a specificare esplicitamente gli argomenti del tipo.

Qual è la sintassi corretta per questo?

risposta

89

DataTable.Rows restituisce un DataRowCollection che implementa solo IEnumerable, non IEnumerable<DataRow>. Utilizzare il metodo AsEnumerable() estensione DataTable (da DataTableExtensions) invece:

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

D'oh! Batti al colpo (di pochi secondi)! – JaredReisinger

+0

questa stessa estensione sarebbe disponibile per altre raccolte che implementano IEnumerable? come ad esempio TreeNodeCollection? o dovrei creare questa estensione da solo? –

+0

@Scott: Dovresti scriverlo da solo - perché altrimenti non si saprà quale tipo di "IEnumerable " restituire, se vedi cosa intendo. –

7

Parallel.ForEach() si aspetta il primo argomento sia un IEnumerable <> tipo. DataTable.Rows non lo è, ma puoi trasformarlo in uno con il metodo di estensione AsEnumerable(). Prova:

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

questo è meglio che la risposta accettata, perché questo non ha bisogno di fare riferimento System.Data.DataSetExtensions:

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

Per utilizzare ForEach con una collezione non generico, è possibile utilizzare la Trasmetti il ​​metodo di estensione per convertire la raccolta in una raccolta generica, come mostrato in questo esempio.

+1

Ma tieni presente questo , da [Cast docs] (https://msdn.microsoft.com/en-us/library/bb341406 (v = vs.110) .aspx): "Se un elemento non può essere lanciato per digitare TResult, questo metodo genererà un'eccezione. Per ottenere solo quegli elementi che possono essere espressi per digitare TResult, utilizzare il metodo OfType anziché Cast (IEnumerable). " – ALEXintlsos

0

Ho dovuto modificare la risposta di Jon Skeet per farlo funzionare.

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