c# - Parallel.For 循环卡住

标签 c# datatable parallel-processing

我正在尝试向 DataTable 添加一些并行信息,但如果循环太长,它会卡住或只花费大量时间,比通常的 for 循环更多的时间,这是我的并行代码。对于循环:

Parallel.For(1, linii.Length, index =>
                 {
                     DataRow drRow = dtResult.NewRow();
                     alResult = CSVParser(linii[index], txtDelimiter, txtQualifier);

                     for (int i = 0; i < alResult.Count; i++)
                     {
                         drRow[i] = alResult[i];
                     }
                     dtResult.Rows.Add(drRow);
                 }
             );

怎么了?这个 Parallel.For 循环比普通循环花费更多时间,有什么问题吗?

谢谢!

最佳答案

你不能改变来自 2 个不同线程的 DataTable;它出错。 DataTable 不尝试 是线程安全的。所以:不要那样做。只需从一个线程执行此操作。您很可能受到 IO 的限制,因此您应该只在单个线程上将其作为流来执行。看起来您正在处理文本数据。您似乎有一个 string[] 行,也许是 File.ReadAllLines() ?嗯,这里很糟糕:

  1. 它强制所有内容加载到内存中
  2. 您必须等待将其全部加载到内存中
  3. CSV 是一种多行格式;不保证 1 行 == 1 行

应该做的是使用代码项目中的 CsvReader 之类的东西,但即使您只想一次使用一行,也可以使用 StreamReader:

using(var file = File.OpenText(path)) {
    string line;
    while((line = file.ReadLine()) != null) {
        // process this line
        alResult = CSVParser(line, txtDelimiter, txtQualifier);

        for (int i = 0; i < alResult.Count; i++)
        {
            drRow[i] = alResult[i];
        }
        dtResult.Rows.Add(drRow);
    }
}

使用 Parallel不会更快,所以我没有尝试这样做。 IO 是你的瓶颈。锁定是一种选择,但它不会对您有很大帮助。

顺便说一句,我注意到 alResult 没有在循环内声明。这意味着在您的原始代码中,alResult 是一个捕获的变量,它在所有 循环迭代之间共享 - 这意味着你已经可怕地覆盖了每一行。


编辑:说明为什么 Parallel 与从文件中读取 1,000,000 行无关:

方法一:使用ReadAllLines加载行,然后使用Parallel进行处理;这会花费 [固定时间] 用于物理文件 IO,然后我们并行化。 CPU 的工作量很少,我们基本上已经花费了[固定时间]。但是,我们增加了很多线程开销和内存开销,甚至在所有文件加载完成之前我们都无法开始

方法 2:使用流式 API;逐行阅读每一行 - 处理每一行并添加它。这里的成本基本上又是:[固定时间]实际IO带宽来加载文件。但;我们现在没有线程开销,没有同步冲突,没有大内存要分配,我们马上开始填充表。

方法 3:如果您真的想要,第三种方法是读取器/写入器队列,使用一个专用线程处理文件 IO 并将行排入队列,第二个线程执行 数据表。坦率地说,它有很多移动部件,第二个线程将花费 95% 的时间等待文件中的数据;坚持方法 2!

关于c# - Parallel.For 循环卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11883897/

相关文章:

c - 如何在 CUDA/cublas 中转置矩阵?

python - 并行目录遍历 python

c# - Azure Cosmos-db 重命名文档属性

c# - 用鼠标绘图会导致像素之间出现间隙

C# 将数据与数据库分开存储

javascript - 对象不支持属性或方法 'dataTable'错误

javascript - 如何在数据表中自动修复下一页

c#用一行c#代码播放声音

javascript - 使用 ajax 从 mysql 填充 jQuery 数据表

python - 如何在 Python 中并行化列表理解计算?