C#中foreach循环的性能优化

Ste*_*lan 8 c# parallel-processing performance foreach

我有一个方法:

IList<string> pages = new List<string>();
foreach (var node in nodes)
{
    try
    {
        string temp = DoSomeComplicatedModificationOnNode(node);
        if (temp.ToLower().Contains(path))
        {
            pages.Add(node.Title);
        }
    }
    catch (Exception)
    {
        continue;
    }
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,DoSomeComplicatedModificationOnNode()会给出异常,这就是使用try {} catch块的原因 - 我可以跳过给出异常的项目.节点数包含数千个项目,项目具有多个属性.如何优化此循环?我在考虑Parallel.Foreach,但是下面的代码给出了一个错误"Missing current principal":

IList<string> pages = new List<string>();
Parallel.ForEach(pageNodes, node =>
{
    try
    {
        string temp = DoSomeComplicatedModificationOnNode(node);
        if (temp.ToLower().Contains(path))
        {
            pages.Add(node.Title);
        }
    }
    catch (Exception)
    {
    }
});
Run Code Online (Sandbox Code Playgroud)

小智 9

在C#中,通用列表不是线程安全的,因此您无法在并行循环中添加项.

我建议使用另一个类,如ConcurrentBag,ConcurrentStack或ConcurrentQueue.

var pages = new ConcurrentBag<string>();
Parallel.ForEach(pageNodes, node =>
{
    try
    {
        string temp = DoSomeComplicatedModificationOnNode(node);
        if (temp.ToLower().Contains(path))
            pages.Add(node.Title);
    }
    catch (Exception)
    {
        throw;
    }
});
Run Code Online (Sandbox Code Playgroud)

请记住,并行任务是无序的,如果您需要订单,则必须在并行中使用索引.列表只是thead-save用于阅读.

System.Threading.Tasks.Parallel.For(0, pageNodes.Count, index =>
{
    string node = pageNodes[index];

    try
    {
        string temp = DoSomeComplicatedModificationOnNode(node);
        if (temp.ToLower().Contains(path))
            pages.Add(MyPage(index, node.Title));
    }
    catch (Exception)
    {
        throw;
    }
});
Run Code Online (Sandbox Code Playgroud)


gdi*_*dir 2

List<T> 在大多数情况下不是线程安全的。看一下线程安全集合,例如 ConcurrentBag<T>。

  • 无知的评论。parallel.foreach 的存在与列表的并行性无关。List&lt;T&gt; 对于插入来说不是线程安全的,这是一个问题。Parallel.Foreach 有很多用途 - 在使用非线程保存容器的代码块上滥用它不是其中之一。 (11认同)