PLINQ exception
本文关键字:exception PLINQ | 更新日期: 2023-09-27 18:11:32
我使用PLINQ与下面的代码:
static void Main(string[] args)
{
var lt = new List<int>() {1,2,3,4,5};
try
{
var nlt = lt.AsParallel().Select(Test).ToList();
}
catch (AggregateException e)
{
foreach (var ex in e.InnerExceptions)
{
Console.WriteLine(ex.Message);
}
}
}
private static bool Test(int n)
{
if (n == 1)
{
Thread.Sleep(1000);
}
if (n == 3)
{
Thread.Sleep(3000);
}
if (n == 5)
{
Thread.Sleep(5000);
}
if (n == 2 || n == 4)
{
throw new Exception("New exception");
}
Console.WriteLine("element : {0}", n);
return true;
}
结果是aggregateException总是在5s之后抛出(直到最后一个线程完成)。似乎如果某些线程抛出异常,线程的其余部分仍将继续运行。在最后一个线程完成后,框架聚合所有异常并将它们包装在aggregateException中。
如果10个线程中有3个抛出异常,它将等待其余7个线程完成并在结束时抛出aggreagteException,这是框架的行为吗?
然而,当我看到这个文档时:https://msdn.microsoft.com/en-us/library/dd460712 (v = vs.110) . aspx
在抛出异常后查询不能继续。当应用程序代码捕获异常时,PLINQ已经停止了所有线程上的查询。
我想知道为什么我的代码不这样做?如果抛出异常后查询不能继续,元素1,3,5将永远不会被打印,因为异常已经抛出。
从您提供的链接:
当异常被允许冒泡回连接线程时,那么在引发异常后,查询可能会继续处理某些项。
albahari文章的这一部分更好地解释了正在发生的事情:
PLINQ和Parallel类在遇到第一个异常时结束查询或循环执行,不再处理任何进一步的元素或循环体。然而,在当前循环完成之前,可能会抛出更多异常。AggregateException中的第一个异常在InnerException属性中可见。
当抛出异常时,不再处理集合中的任何值。然而,当抛出异常时,已经为所有5个int调用了方法Test(int)
。在这种情况下,PLINQ将等待这些方法调用(当前周期),并在它们全部完成时抛出AggregateException
。