【问题标题】:Parallel for data structures并行数据结构
【发布时间】:2020-04-07 06:39:25
【问题描述】:

我正在使用 parallel.for 在数据表上循环。循环中改变的值是 cirNumb,我用这个值查询一个数据表来填充一个IEnumerable<DataRow> 类型的对象。然后我调用一个结构的实例,我必须将此集合IEnumerable<DataRow> 传递给结构。在结构内部,我使用以前的集合来填充数据表,但我发现有时结果是正确的,有时不是,我想错误在于将 IEnumerable<DataRow> 分配给数据表。 这里有一些代码:

Parallel.For(0, dtCir.Rows.Count, (i, state) =>
{     
    int cirNumb = Convert.ToInt32(dtCir.Rows[i]["no_of_circuits"]);
    IEnumerable<DataRow> dtConnectionSizeLoop = from dtConn in 
                                dtConnectionDatabase.AsEnumerable().AsParallel() 
                                where dtConn.Field<Int32>("no_of_circuits") == cirNumb

    CalculateDC calcDC;
    calcDC = new CalculateDC();
    calcDC.SetParameters(...,dtConnectionSizeLoop,...);
   //do some stuffs
}

struct SetParameters 方法做了一些事情,并将对象 IEnumerable&lt;DataRow&gt; 分配给数据表:

DataTable var_dtConnectionSize = dtConnectionSize.CopyToDataTable();

有人可以帮帮我吗?

【问题讨论】:

  • 让我们退后一步。你为什么要考虑使用Parallel根本?如果只使用普通循环(没有ParallelAsParallel),代码需要多长时间才能运行?
  • 我使用它是因为我在 SetParameters 方法中有一些密集的数学演算,通过这种方式我可以并行化这些操作。使用普通循环,时间约为 60 秒。
  • 先加载数据,并行计算,再存入数据库

标签: c# multithreading datatable thread-safety parallel.for


【解决方案1】:

ADO.NET 类(DataSetDatatable 等)不是线程安全的,因此尝试在不同步的情况下从多个线程并行操作它们可能很容易破坏它们的内部状态。您观察到的错误结果可能是由这种内部状态损坏引起的。内部状态损坏的对象的行为是未定义的。它可能会抛出异常、产生不正确的结果、导致死锁等。没人知道。

为了保护对象免受损坏,您必须在代码中引入线程同步 (locks)。在受保护的代码块内,一次只允许一个线程进入。如果锁被长时间持有,这可能会产生争用,因此尽快释放锁很重要。任何不需要保护的代码都应该在受保护区域之外。

我可以写一些例子,但是从你的方法的命名来看,哪个方法需要保护,哪个不需要保护并不明显。您的代码的每一行都可能操作线程不安全的对象,在这种情况下,所有对象都应该受到保护,从而完全抵消了并行性在您的情况下的好处。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    相关资源
    最近更新 更多