为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
海绵宝宝撒 2022-01-15 19:21:36
使用 Linqpad 创建了一个简单的程序,我在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();        }    }细节:有两个版本的 Test,一个带有显式 Try Catch,另一个没有两者都具有相似的不一致行为,以至于在 Test1 中,即使本地 try catch 也不会打印该值可以有第三个版本Test3,它总是作为异常没有明确地从并行循环中抛出Dump是一个 linqpad 打印调用替换它Console.WriteLine在视觉工作室这里有一个选项define ,它收集a中的所有异常,ConcurrentQueue稍后将它们作为聚合异常抛出,但是为什么当前代码不能按预期工作,我不太确定。在这种情况下,我们期望输出为:1 - Odd value exception 3 - Odd value exception 5 - Odd value exception但是其中一些是随机跳过的,在一个简单的程序中也是如此,在一个复杂的程序中会有更多的失误,这会做更多的工作
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

这完全是预期的行为。

请参阅文档

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

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

因此,行为将显得不可预测。您无权期望所有子任务都会执行。这不是 Parallel.For 循环的合同。

当您将更多项目添加到源列表时,差异会更加明显。输出将始终显示 ThreadPool.MinThreads 附近的许多异常。


查看完整回答
反对 回复 2022-01-15
  • 1 回答
  • 0 关注
  • 188 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信