转载自MGEN
和for/foreach中发生异常的表现一样,Parallel循环中的任何异常都会使整个循环终止,注意由于整个循环是分块同时进行的,因此整个循环不会立即终止(如果有一个线程正在进行长时间工作的话,而且是发生在CancellationToken的ThrowIfCancellationRequested方法之后)。
代码:
try
{
Parallel.For(0, 5, (i) =>
{
throw new Exception("异常。迭代数字:" + i);
});
}
catch (AggregateException ae)
{
foreach (var exp in ae.InnerExceptions)
Console.WriteLine(exp.Message);
}
将会输出0-4的子集(也有可能是0-4全部输出,由于5个线程都快速运行完成)。
与Parallel.For和ForEach不一样,Parallel.Invoke总是会把所有任务都执行完,然后把所有的异常包装在AggregateException中。
来看这段代码:
try
{
Parallel.Invoke(() => { throw new Exception("1"); },
() => { Thread.Sleep(1500); throw new Exception("2"); },
() => { Thread.Sleep(3000); throw new Exception("3"); });
}
catch (AggregateException ae)
{
foreach (var ex in ae.InnerExceptions)
Console.WriteLine(ex.Message);
}
结果会输出:
3
2
1
Task.WaitAll和Parallel.Invoke类似,任何一个(或多个)Task的异常不会影响任何其他Task的执行。
try
{
var t1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(700);
throw new Exception("1");
});
var t2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
throw new Exception("2");
});
Task.WaitAll(t1, t2);
}
catch (AggregateException ae)
{
foreach (var exp in ae.InnerExceptions)
Console.WriteLine(exp.Message);
}
同样会输出:
2
1
两个异常都会在AggregateException中的InnerExceptions属性中。
对于Task执行的异常(而不是Task.WaitAll),可以参考这篇文章:
.NET(C#) TPL:Task中未觉察异常和TaskScheduler.UnobservedTaskException事件
对于取消处理的异常可以参考:
.NET(C#) TPL:Task, Parallel, PLINQ中取消操作后的OperationCanceledException异常
Related Posts:
.NET(C#) TPL:Task, Parallel, PLINQ中取消操作后的OperationCanceledException异常
.NET(C#) TPL:Task中未觉察异常和TaskScheduler.UnobservedTaskException事件
.NET(C#):多个await和和异常处理
.NET(C#) TPL:TaskFactory.FromAsync与委托的异步调用