2010-08-04 84 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 = ""; 
});