本文主要是要说明PLINQ中如果发生了异常(除取消任务以外的异常),那么将会返回一个aggregateexception(因为所有并行查询中发生的异常都会被抛出),需要对其中的innerexception进行进一步处理。
首先来看普通Linq查询中发生的异常:由于是顺序执行查询,因此当碰到了对应的第一个异常时便自动捕获,也无须考虑线程的问题,因为是在同一个线程中。
IEnumerable<int> numbers = Enumerable.Range(-5, 10);
var query = from number in numbers select 100 / number;
try
{
foreach(var n in query)
Console.WriteLine(n);
}
catch (DivideByZeroException)
{
Console.WriteLine("Divided by zero!");
}
Console.WriteLine("---");
Console.WriteLine("Sequential LINQ query processing");
Console.WriteLine();
再来看一下并行查询的异常捕获:
var parallelQuery = from number in numbers.AsParallel() select 100 / number; ;
try
{
parallelQuery.ForAll(Console.WriteLine);
}
catch (DivideByZeroException)
{
Console.WriteLine("Divided by zero - usual exception handler!");
}
catch (AggregateException e)
{
e.Flatten().Handle(ex =>
{
if (ex is DivideByZeroException)
{
Console.WriteLine("Divided by zero - aggregate exception handler!");
return true;
}
return false;
});
}
Console.WriteLine("---");
Console.WriteLine("Parallel LINQ query processing and results merging");
遇到这个异常时点击继续即可,无须理会。(原因是VS没有识别到下面我们写的异常处理代码)
可以看到,异常是被第二个catch所捕获,因此这是一个aggregateexception。