代码之家  ›  专栏  ›  技术社区  ›  Mrinal Kamboj

平行。Foreach循环,与显式throw语句的行为不一致

  •  2
  • Mrinal Kamboj  · 技术社区  · 8 年前

    Parallel Foreach 循环,理想情况下,调用方应将其捕获为 Aggregate Exception ,但当我显式抛出异常时,它有时会随机跳过几个异常。我无法理解这种行为,任何能解释的人:

    void Main()
    {
        try
        {
          var intList = new List<int> {1,2,3,4,5,6};
    
          Parallel.ForEach(intList, i => Test1(i));
        }
        catch (AggregateException aggregateException)
        {
            foreach (var ex in aggregateException.Flatten().InnerExceptions)
            {
                ex.Message.Dump();
            }
        }
    }
    
    public void Test1(int i)
    {
        try
        {
            if (i % 2 != 0)
                throw new Exception($"{i} - Odd value exception");
    
        }
        catch(Exception ex)
        {
            ex.Message.Dump();
            throw;
        }
    }
    
    public void Test2(int i)
    {
            if (i % 2 != 0)
                throw new Exception($"{i} - Odd value exception");
    }
    
    public void Test3(int i)
        {
            try
            {
                if (i % 2 != 0)
                    throw new Exception($"{i} - Odd value exception");
    
            }
            catch(Exception ex)
            {
                ex.Message.Dump();
            }
        }
    

    细节:

    1. 两者都有类似的不一致行为,以至于在Test1中,即使是本地try-catch也不会打印值
    2. 可能有第三种版本 Test3
    3. Dump Console.WriteLine 在visualstudio上

    here ,它收集 ConcurrentQueue 稍后将它们作为聚合异常抛出,但为什么当前代码不能按预期工作,我不太清楚。在这种情况下,我们期望输出为:

    1 - Odd value exception
    3 - Odd value exception
    5 - Odd value exception
    

    但其中一些是随机跳过的,即在一个简单的程序中,有更多的遗漏在一个复杂的程序中,这做了更多的工作

    1 回复  |  直到 8 年前
        1
  •  3
  •   bommelding    8 年前

    docs ,

    因此,这种行为将显得不可预测。您无权期望所有子任务都将执行。那不是一个公司的合同平行。用于循环。

    当您向源列表中添加更多项时,差异将更加明显。 输出将始终显示线程池.MinThreads.