【问题标题】:How to break out of an inner nested Parallel.Foreach loop in C#?如何打破 C# 中的内部嵌套 Parallel.Foreach 循环?
【发布时间】:2021-05-01 14:04:54
【问题描述】:

为什么这个 break 语句不起作用?我的目标是只跳出内循环,但继续处理外循环。无论我做什么,它都会击中Console.WriteLine()

我试过了:

  1. innerLoopState.Break()
  2. innerLoopState.Stop()

Console.WriteLine()之前不要停止循环...

private static ParallelOptions ParallelCityOptions => new ParallelOptions
{
    MaxDegreeOfParallelism = 2
};

private static ParallelOptions ParallelPeopleOptions => new ParallelOptions
{
    MaxDegreeOfParallelism = 3
}

[Test]
public void NestedParallelForeach()
{
    var listOfCities = new List<string> {"Atlanta", "Denver", "Scranton",};
    var listOfPeople = new List<string>() {"Bob", "Sally", "Craig", "Bill"};

    Parallel.ForEach(listOfCities, ParallelCityOptions, city =>
    {
        Parallel.ForEach(listOfPeople, ParallelPeopleOptions, (person, innerLoopState) =>
        {

            if (person == "Bill")
            {
                // do something
                innerLoopState.Break();
                Console.WriteLine("Should never hit this line.");
            }
        });
    });
}

【问题讨论】:

    标签: c# loops nested-loops parallel.foreach .net-framework-4.8


    【解决方案1】:

    你的问题的直接答案是:咖喱外循环状态并按你的意愿打破它:

    Parallel.ForEach(listOfCities, ParallelCityOptions, (city, outerLoopState) =>
    {
        Parallel.ForEach(listOfPeople, ParallelPeopleOptions, (person, innerLoopState) =>
        {
    
            if (person == "Bill")
            {
                // do something
                outerLoopState.Break();
                innerLoopState.Break();
                Console.WriteLine("Should never hit this line.");
            }
        });
    });
    

    但是,数组中的所有元素都将由您的代码一次处理,因为与现代计算机的内核数量相比,内核数量太少了。简单地请求并行循环中断不会神奇地中断所有线程,它只会阻止新线程的处理。

    【讨论】:

    • 这也会跳出外循环吗?我希望继续在城市中循环,但如果是“比尔”,就离开特定的城市。我有一个真实世界的情况,为了简洁起见只是简化了它。
    • 你的问题是如何跳出 nested 循环,我是不是看错了?
    • 我已经改写了这个问题,以更清楚地代表我的目标。对于那个很抱歉。我的意思是问如何只跳出内循环,但继续处理外循环
    • 那么您已经编写了正确的代码。如果您问为什么执行超出Break,那是因为正如我所说的Break 标志不应处理任何新项目,仅此而已。如果您不想点击下一行,只需将其删除即可。或者在它之前添加一个return;,如果这对您更有意义的话。
    • 这正是我遇到的问题。我需要它在innerLoopState.Break() 之后不执行代码。听起来我也只需要添加一个return。如果你改写你的答案,我可以接受它给你代表。感谢您的帮助!
    猜你喜欢
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2012-01-19
    • 1970-01-01
    • 2012-09-19
    • 2019-01-30
    相关资源
    最近更新 更多