我试图抛出并捕获一个AggregateException。
我没有在C#上使用过多异常,但是发现的行为有点令人惊讶。
我的代码是:
var numbers = Enumerable.Range(0, 20);
try
{
var parallelResult = numbers.AsParallel()
.Where(i => IsEven(i));
parallelResult.ForAll(e => Console.WriteLine(e));
}
catch (AggregateException e)
{
Console.WriteLine("There was {0} exceptions", e.InnerExceptions.Count());
}
它正在调用函数IsEven
private static bool IsEven(int i)
{
if (i % 10 == 0)
throw new AggregateException("i");
return i % 2 == 0;
}
这引发了AggregateException。
我希望代码写出0,20范围内的每个偶数,两次“有1个异常(exception)”。
我得到的是打印了一些数字(它们是ForAll的随机原因),然后引发了异常,但没有捕获到异常,程序停止了。
我想念什么吗?
最佳答案
这实际上很有趣。我认为问题在于您以一种意外的方式使用AggregateException
,这会导致PLINQ代码内部出现错误。AggregateException
的全部要点是将可能在并行过程中同时(或几乎如此)发生的多个异常组合在一起。因此,AggregateException
至少应具有一个内部异常。但是,您将抛出new AggregateException("i")
,它没有内部异常。 PLINQ代码尝试检查InnerExceptions
属性,遇到某种错误(可能是NullPointerException
),然后似乎陷入某种循环。可以说这是PLINQ中的一个错误,因为您对AggregateException
使用了有效的构造函数,即使它是不寻常的也是如此。
如在其他地方指出的那样,抛出ArgumentException
在语义上会更正确。但是,您可以通过抛出正确构造的AggregateException
来获得所需的行为,例如,通过将IsEven
函数更改为以下形式:
private static bool IsEven(int i)
{
if (i % 10 == 0){
//This is still weird
//You shouldn't do this. Just throw the ArgumentException.
throw new AggregateException(new ArgumentException("I hate multiples of 10"));
}
return i % 2 == 0;
}
我认为这个故事的寓意是除非真正知道自己在做什么,否则不要抛出
AggregateException
,尤其是如果您已经在基于并行或基于Task
的某种操作中。关于c# - 捕捉AggregateException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19266338/