Parallel.ForEach对DataTable工作太慢了

时间:2015-07-01 03:05:45

标签: c# foreach datatable parallel-processing parallel.foreach

我在DTable中实现Parallel.ForEach时遇到问题。以下是我正在实施的示例代码:

Parallel.ForEach(dTable4.AsEnumerable(), row4 =>
            {
                string getCondition = row4[1].ToString();
                getCondition = EvaluateCondExpression(getCondition);  //Evaluates CM for value (CM1==2 && CM2<5);
                Expression e = new Expression(getCondition); //getCondition = (2==2 && 2<5)
                var evalutateCondition = e.Evaluate();
                if (Convert.ToBoolean(evalutateCondition))
                {
                   //Write string to TextBox
                }
             }

当我运行它时,线程没有被有效管理,并且它比foreach循环花费太多时间。 在从GUI组合框和numericUpDown检查用户提供的参数后,EvaluateCondExpression函数返回值

private string EvaluateCondExpression(string getCondition)
    {
        string[] splitgetCondition1 = SeprateCharacter(getCondition);
        foreach (string oneCondition in splitgetCondition1)
        {
            string conditionValue = oneCondition;
            if (oneCondition.Contains("CM"))
            {
                conditionValue = RemoveMultipleChar(conditionValue.Replace('!', ' ').Trim());
                string getInputNumber = getTableOneInputNo(conditionValue, dTable1);
                string tableOneValue = checkComboxValue(m_comboBox, getInputNumber);

                getCondition = getCondition.Replace(conditionValue, tableOneValue);
            }
        }
        return getCondition;
    }

串行ForEach计算花费了太多时间,所以我想应用Parallel.ForEach迭代,但遗憾的是它无法正常工作。任何人都可以建议我如何最大限度地提高性能以及我在Parallel.ForEach中做错了什么。

3 个答案:

答案 0 :(得分:3)

通过使用传统的foreach,在Task中包装每次迭代,您可能会看到性能提升。将每次迭代的任务添加到集合中,然后在foreach调用之外调用Task.WhenAll(tasks);如果有什么它可以让你有能力等待昂贵的并行过程。

您可以将Parallel.ForEach的内容转换为Select Linq查询,该查询将每次迭代转换为Task。生成的任务集合可以提供给Task.WhenAll方法以等待

这可能无法解决您所看到的性能瓶颈,但这至少会让您等待并行进程并释放UI线程。

答案 1 :(得分:2)

运行循环的一次迭代需要多长时间?你运行了多少次迭代?通常,Parallel.Foreach()非常适合运行循环,其中每次迭代可能需要相当长的时间。如果你有相当快速操作的许多迭代,你将花费大量额外的开销来生成和管理线程,这可能是你所看到的。有关此类场景的更多信息,请参阅此MSDN文章:

https://msdn.microsoft.com/en-us/library/dd560853(v=vs.110).aspx

<强>更新

Here是Parallel.Foreach()和await Task.WhenAll()的良好比较。

答案 2 :(得分:2)

使用Parallel.ForEach时,您可以对代码进行以下修改,尤其是对于长时间运行的任务

Parallel.ForEach( dTable4.AsEnumerable(), new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount}, row4 = >

这将确保Parallel.ForEach不会启动datatable中每个数据点的线程,它只会动态地根据环境处理器/核心的数量生成线程,从而减少争用和线程上下文切换。但理想情况下,如上所述,您可以为长时间运行的任务规划异步模式。

我看到你正在更新Parallel循环中的UI控件,为此你无论如何都需要UI线程上下文,否则它将是一个异常。无论如何,Async在UI线程上下文中运行