是Parallel.forEach(DataTable.AsEnumerable()线程安全

时间:2012-02-15 16:31:46

标签: c# .net task-parallel-library

使用时如下

Parallel.ForEach(DataTable.AsEnumerable(), dr => {

    string str = dr["field1"].ToString();
     //.... other stuff
    dr["f1"] = o.A;
    dr["f2"] = o.B;
    dr["f3"] = o.C;

});

每个线程在自己的数据行上工作

我会假设不是,但有关于假设的这句话......

3 个答案:

答案 0 :(得分:4)

DataTable对于写操作不是线程安全的。当您同时更改行时,您将更改DataTable的状态,因此这将导致问题。

答案 1 :(得分:4)

DataRow类的documentation明确指出

  

此类型对于多线程读取操作是安全的。你必须   同步任何写操作。

不能再具体了。

在任何情况下,并行写入数据表可能无法很好地扩展。当多个线程访问共享状态并且单个数据表显然是共享状态时,可伸缩性会受到影响。更重要的是,除非您使用NUMA硬件,否则您的CPU内核将争夺对相同内存总线的访问权。

更好的解决方案是在单独的结构中返回并行处理(“其他内容”)中的任何结果(例如one of the concurrent collections),并在循环结束时从单个线程应用更改。

另一种选择是使用PLINQ来计算结果,并使用简单的foreach迭代它们以将更改应用回DataTable。

更好的解决方案是完全丢弃原始数据表并返回包含所需字段的新对象。除非您的代码要求结果是DataTable,否则您只需将结果作为IEnumerable

返回

答案 2 :(得分:1)

如果对这些列中的任何列编制索引,那肯定是不安全的 如果没有,可能是安全的,但我不这么认为。