[英]Parallel.Foreach loop, inconsistent behavior with explicit throw statement
Created a simple program using Linqpad, where I am throwing an exception explicitly in the Parallel Foreach
loop, which ideally shall be caught in the caller as Aggregate Exception
, but when I explicitly throw the exception, it sometimes skip out few exceptions on random basis. 使用Linqpad创建了一个简单程序,其中我在
Parallel Foreach
循环中显式抛出一个异常,理想情况下,该Aggregate Exception
应作为Aggregate Exception
被捕获在调用方中,但是当我显式抛出该异常时,它有时会随机地跳过一些异常。 I am not able to understand the behavior, anyone who can explain: 任何人都可以解释的行为,我无法理解:
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();
}
}
Test3
which always work as exception is not explicitly thrown out of the parallel loop Test3
,它总是可以正常工作,因为没有明确地将异常排除在并行循环之外 Dump
is a linqpad print call replace it by Console.WriteLine
on the visual studio Dump
是linqpad打印调用,在Visual Studio中由Console.WriteLine
代替 There's an option define here , which collects all exceptions in a ConcurrentQueue
and throw them later as aggregated exception, but why the current code doesn't work as expected, I am not very sure. 有一个选项定义在这里 ,收集在所有异常
ConcurrentQueue
它们扔后来由于聚集的例外,但为什么如预期当前代码不工作,我不是很肯定。 In this case we expect Output to be: 在这种情况下,我们期望输出为:
1 - Odd value exception
3 - Odd value exception
5 - Odd value exception
but some of them are randomly skipped, that too in a simple program, there are much more miss in a complex program, which do far more work 但是其中一些被随机跳过,在一个简单的程序中,复杂程序中的遗漏也更多,而后者的工作量则更多
This is entirely expected behaviour. 这完全是预期的行为。
an unhandled exception causes the loop to terminate immediately
未处理的异常导致循环立即终止
When you throw an exception, no new Tasks will be scheduled. 引发异常时,不会安排任何新任务。
So the behaviour will appear unpredictable. 因此,该行为将显得不可预测。 You have no right to expect that all subtasks will execute.
您无权期望所有子任务都将执行。 That is not the contract of a Parallel.For loop.
那不是Parallel.For循环的约定。
The difference will be much clearer when you add more items to the source list. 当您向源列表中添加更多项目时,差异将更加明显。 The output will always show a number of exceptions in the neighbourhood of ThreadPool.MinThreads.
输出将始终在ThreadPool.MinThreads附近显示许多异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.