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:
- There two versions of Test, one with explicit Try Catch and other without
- Both have similar inconsistent behavior to the extent that in Test1, even local try catch doesn't print the value
- There can be third version
Test3which always work as exception is not explicitly thrown out of the parallel loop Dumpis a linqpad print call replace it byConsole.WriteLineon 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
Parallel.For/Foreachis meant for data parallelism. It creates roughly as many worker tasks as there are cores, partitions the data and feeds each partition to a task. It doesn't make sense of computation to proceed if any of those tasks throws.