Parallel.Foreach loop, inconsistent behavior with explicit throw statement

那年仲夏 提交于 2019-12-31 02:43:10

问题


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

Details:

  1. There two versions of Test, one with explicit Try Catch and other without
  2. Both have similar inconsistent behavior to the extent that in Test1, even local try catch doesn't print the value
  3. There can be third version Test3 which always work as exception is not explicitly thrown out of the parallel loop
  4. Dump is a linqpad print call replace it by Console.WriteLine on the visual studio

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. 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


回答1:


This is entirely expected behaviour.

See the docs,

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.

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.



来源:https://stackoverflow.com/questions/52309855/parallel-foreach-loop-inconsistent-behavior-with-explicit-throw-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!