C# Parallel.Foreach循环,行为与显式throw语句不一致

C# Parallel.Foreach循环,行为与显式throw语句不一致,c#,.net,task-parallel-library,parallel.foreach,aggregateexception,C#,.net,Task Parallel Library,Parallel.foreach,Aggregateexception,使用Linqpad创建了一个简单的程序,我在并行Foreach循环中显式抛出一个异常,理想情况下,调用方会将其捕获为聚合异常,但当我显式抛出异常时,它有时会随机跳过几个异常。我无法理解这种行为,任何能解释的人: void Main() { try { var intList = new List<int> {1,2,3,4,5,6}; Parallel.ForEach(intList, i => Test1(i)); }

使用Linqpad创建了一个简单的程序,我在
并行Foreach
循环中显式抛出一个异常,理想情况下,调用方会将其捕获为
聚合异常
,但当我显式抛出异常时,它有时会随机跳过几个异常。我无法理解这种行为,任何能解释的人:

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();
        }
    }

但其中一些是随机跳过的,也就是说,在一个简单的程序中,在一个复杂的程序中会有更多的遗漏,而复杂的程序会做更多的工作

这完全是预期的行为

看,

未处理的异常会导致循环立即终止

当您抛出异常时,将不会安排新任务

因此,这种行为将显得不可预测。您无权期望所有子任务都将执行。这不是并行的For循环的契约

当您向源列表中添加更多项时,差异将更加明显。
输出将始终显示ThreadPool.MinThreads附近的一些异常

你的意思是,不打印的原因是并行循环本身正在退出,而显式任务则不应如此。我不知道“显式任务”是什么意思,但我认为是的。请参阅我的编辑中的链接。
任务
与TPL任务中的链接一样,它们与并行循环不同,并且肯定是相同的executed@MrinalKamboj不一定每个
并行1:1。ForEach
迭代和
任务
。“”@MrinalKamboj Parallel.Foreach将任务用作辅助任务。它对数据进行分区,并将每个分区提供给不同的工作者。这意味着数据并行性,这就是为什么它使用与内核数量大致相同的工人来确保CPU完全被占用的原因。在一台4核机器上,它将创建4个任务来处理800K项,并将其中的200K项传递给每个工人。如果没有,CPU将浪费所有时间从一个任务切换到另一个任务,而不是processing@MickyD不,我不知道,这纯粹是为了学习,否则MSDN链接中的模式非常好。感谢并行。For/Foreach用于数据并行。它创建的辅助任务数量与内核数量大致相同,对数据进行分区,并将每个分区提供给一个任务。如果这些任务中有任何一个抛出,那么继续进行计算是没有意义的。
1 - Odd value exception
3 - Odd value exception
5 - Odd value exception