2010-08-04 71 views
42

我想使用新的Parallel.ForEach函數來遍歷數據表,並對每一行執行操作。我想下面的代碼轉換:Parallel ForEach on DataTable

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

要將此代碼:

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

當我運行新的代碼中,我得到的錯誤:

的方法的類型參數「系統.Threading.Tasks.Parallel.ForEach(System.Collections.Generic.IEnumerable,System.Action)'不能從使用情況中推斷出來。嘗試明確指定類型參數。

這是什麼正確的語法?

回答

89

DataTable.Rows返回DataRowCollection,它只實現IEnumerable而不是IEnumerable<DataRow>。使用上DataTableAsEnumerable()擴展方法(從DataTableExtensions)代替:

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

D'oh!擊敗拳頭(僅僅幾秒)! – JaredReisinger 2010-08-04 18:31:09

+0

這個擴展是否可用於實現IEnumerable的其他集合?如TreeNodeCollection?或者我必須自己創建這個擴展名? – 2010-11-12 12:29:56

+0

@Scott:你必須自己編寫它 - 因爲否則它不會知道返回哪種類型的'IEnumerable ',如果你明白我的意思。 – 2010-11-12 21:54:34

7

Parallel.ForEach()預計的第一個參數是一個IEnumerable <>類型。 DataTable.Rows不是,但可以使用AsEnumerable()擴展方法將它變成一個。嘗試:

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

這比接受的答案更好,因爲這並不需要參考System.Data.DataSetExtensions:

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

要使用非泛型集合使用的ForEach,您可以使用Cast擴展方法將集合轉換爲泛型集合,如本例所示。

+1

但請記住這一點,來自[Cast docs](https://msdn.microsoft.com/en-us/library/bb341406(v = vs.110).aspx):「如果一個元素不能轉換爲鍵入TResult,則此方法將拋出一個例外爲了只獲得那些可以強制類型爲TResult的元素,可以使用OfType 而不是Cast (IEnumerable)。「 – ALEXintlsos 2017-10-11 21:16:52

0

我不得不修改喬恩Skeet的答案,使其工作。

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