C# 我捕获的AggregateException没有我期望的异常

C# 我捕获的AggregateException没有我期望的异常,c#,.net,exception,task-parallel-library,C#,.net,Exception,Task Parallel Library,我正在使用任务并行库设置一系列任务,如下所示,但我得到了一个奇怪的异常处理经验,我不理解 我使用Parallel.ForEach并调用一个包含对以下方法的调用的操作。这个Parallel.ForEach被包装在一个try…catch(AggregateException)中,当一个异常发生时——就像它在一个并行分支中发生的那样——一个SchemaValidation异常,那么我希望在AggregateException中看到这一点 然而,我得到的是“一个任务被取消了”——TaskCanceled

我正在使用任务并行库设置一系列任务,如下所示,但我得到了一个奇怪的异常处理经验,我不理解

我使用Parallel.ForEach并调用一个包含对以下方法的调用的操作。这个Parallel.ForEach被包装在一个try…catch(AggregateException)中,当一个异常发生时——就像它在一个并行分支中发生的那样——一个SchemaValidation异常,那么我希望在AggregateException中看到这一点

然而,我得到的是“一个任务被取消了”——TaskCanceledException。我的SchemaValidationException去哪了

        private static void ProcessChunk(Task<ISelectedChunk> selectionTask, 
                                     IRepository repository, 
                                     IIdentifiedExtractChunk identifiedExtractChunk, 
                                     IBatchRunConfiguration batchRunConfiguration, 
                                     IBatchRun batchRun, 
                                     ILog log, 
                                     IAuthenticationCertificate authenticationCertificate, 
                                     IFileSystem fileSystem,
                                     long batchRunRid)
    {
        var transformationTask = selectionTask.ContinueWith(TransformationFunction.Transformation(identifiedExtractChunk, batchRunConfiguration, batchRun),
                                                            TaskContinuationOptions.NotOnFaulted);

        var schemaValidationTask = transformationTask.ContinueWith(SchemaValidationFunction.SchemaValidationTask(batchRunConfiguration),
                                                                   TaskContinuationOptions.NotOnFaulted);

        var compressTask = schemaValidationTask.ContinueWith(CompressFunction.CompressTask(identifiedExtractChunk),
                                                             TaskContinuationOptions.NotOnFaulted);

        var encryptTask = compressTask.ContinueWith(EncryptionFunction.EncryptTask(authenticationCertificate),
                                                    TaskContinuationOptions.NotOnFaulted);

        var fileGenerationTask = encryptTask.ContinueWith(FileGenerationFunction.FileGenerationTask(identifiedExtractChunk, batchRunConfiguration, fileSystem),
                                                          TaskContinuationOptions.NotOnFaulted);
        // Take the time before we start the processing
        DateTime startBatchItemProcessing = DateTime.Now;

        // Start with the Selection Task
        selectionTask.Start();

        // And wait on the last task in the chain
        fileGenerationTask.Wait();

        // Take the time at the end of the processing
        DateTime endBatchItemProcessing = DateTime.Now;

        // Record all the relevant information and add it to the collection 
        IBatchChunkProcessed batchChunkProcessed = GetBatchItemProcessed(identifiedExtractChunk, batchRunRid, fileGenerationTask.Result, transformationTask.Result.Item2, startBatchItemProcessing, endBatchItemProcessing);
        BatchItemsProcessed.Add(batchChunkProcessed);
private static void ProcessChunk(任务选择任务,
i存储库,
IIIdentifiedExtractChunk identifiedExtractChunk,
IBatchRunConfiguration批运行配置,
IBatchRun批处理运行,
ILog日志,
IAAuthenticationCertificate authenticationCertificate,
IFileSystem文件系统,
长批处理(RUNRID)
{
var transformationTask=selectionTask.ContinueWith(TransformationFunction.Transformation(identifiedExtractChunk、batchRunConfiguration、batchRun),
TaskContinuationOptions。无故障);
var schemaValidationTask=transformationTask.ContinueWith(SchemaValidationFunction.schemaValidationTask(batchRunConfiguration),
TaskContinuationOptions。无故障);
var compressTask=schemaValidationTask.ContinueWith(CompressFunction.compressTask(identifiedExtractChunk),
TaskContinuationOptions。无故障);
var encryptTask=compressTask.ContinueWith(EncryptionFunction.encryptTask(authenticationCertificate)),
TaskContinuationOptions。无故障);
var fileGenerationTask=encryptask.ContinueWith(FileGenerationFunction.fileGenerationTask(identifiedExtractChunk、batchRunConfiguration、fileSystem),
TaskContinuationOptions。无故障);
//在我们开始处理之前花点时间
DateTime startBatchItemProcessing=DateTime.Now;
//从选择任务开始
selectionTask.Start();
//然后等待链中的最后一个任务
fileGenerationTask.Wait();
//在处理结束时花点时间
DateTime endBatchItemProcessing=DateTime.Now;
//记录所有相关信息并将其添加到集合中
IBatchChunkProcessed batchChunkProcessed=GetBatchItemProcessed(identifiedExtractChunk、batchRunRid、fileGenerationTask.Result、transformationTask.Result.Item2、startBatchItemProcessing、endBatchItemProcessing);
BatchItemsProcessed.Add(batchChunkProcessed);

让我们稍微简化一下您的代码:

var t1 = Task.Factory.StartNew(a1);
var t2 = t1.ContinueWith(a2, TaskContinuationOptions.NotOnFaulted);
var t3 = t2.ContinueWith(a3, TaskContinuationOptions.NotOnFaulted);

t3.Wait();
现在假设
a1
抛出异常。发生的情况是
t1
出现故障(
t1.Status==TaskStatus.faulted
)。因此,
t2
无法运行(因为
NotOnFaulted
)因此它将被取消。但这并不是您预期的:
t2
不会出错,它将被取消(
t2.Status==TaskStatus.cancelled
)。但这意味着
t3
可以正常运行,如果它不抛出,
t3.Wait()
不会抛出任何异常

如何解决此问题?首先,您可能不应该使用
TaskContinuationOptions。不是有故障的
,而是
TaskContinuationOptions。只使用OnOnOnToCompletion
。但这并不能解决“消失”异常的问题。要解决此问题,我看到了两种可能性:

  • 调用
    Wait()
    在每个继续的开头,不要使用任何
    任务继续选项
    。这意味着您可能会在
    aggregateeexception
    中包装一些异常,它本身包装在另一个
    aggregateeexception
    中。要解决这个问题,您可以使用或。

  • 使用等待所有任务。
    WaitAll()
    将抛出一个
    aggregateeexception
    ,该异常将包含原始异常,并且对于由于第一个异常而取消的每个任务也将抛出
    TaskCanceledException


  • 为什么在这里使用
    Task
    s?为什么不按顺序执行所有方法?代码似乎与问题无关。发布捕获并处理异常的代码。@svick-传入的选择任务是并行的。此外,这些是离散的构建块任务,可以很容易地重新执行sed-可能在其他上下文中执行根任务。@HansPassant-问题不在于异常处理代码-无论我把它放在哪里,我都遇到了同样的问题。我选择了task.WaitAll选项-似乎是最干净的。我现在得到了我想要的异常以及TaskCanceledExceptions。非常感谢。