Создал простую программу с использованием 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
в visual studio
Здесь есть опция определения здесь , котораясобирает все исключения в ConcurrentQueue
и генерирует их позже как агрегированное исключение, но почему текущий код не работает должным образом, я не очень уверен.В этом случае мы ожидаем, что Output будет:
1 - Odd value exception
3 - Odd value exception
5 - Odd value exception
, но некоторые из них пропускаются случайным образом, что также в простой программе, гораздо больше промахов в сложной программе, которая выполняет гораздо больше работы