我捕获的聚合异常没有我期望的异常

本文关键字:异常 没有我 期望 | 更新日期: 2023-09-27 18:29:54

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

我使用 Parallel.ForEach 并调用一个 Action,其中包括对以下方法的调用。这个平行线被包裹在一个尝试...catch(AggregateException(并且当发生异常时 - 就像在其中一个并行分支中一样 - 一个SchemaValidation异常,那么我希望在AggregateException中看到它。

但是,我得到的是"任务被取消" - 任务取消异常。我的 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);

我捕获的聚合异常没有我期望的异常

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

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.Canceled(。但这意味着t3可以正常运行,如果不抛出,t3.Wait()也不会抛出任何异常。

如何解决这个问题?首先,您可能不应该使用 TaskContinuationOptions.NotOnFaulted ,而是TaskContinuationOptions.OnlyOnRanToCompletion。但这并不能解决"消失"异常的问题。为了解决这个问题,我认为有两种可能性:

  1. 在每个延续的开头调用Wait(),不要使用任何TaskContinuationOptions。这意味着你可能会得到一些用AggregateException包裹的异常,它本身被包裹在AggregateException中,它被包裹在另一个AggregateException中,等等。要解决此问题,您可以使用 Flatten()Handle() .

  2. 等待所有任务,通过使用 Task.WaitAll() . WaitAll()将抛出一个AggregateException,其中包含原始异常,并且还会TaskCanceledException由于第一个异常而取消的每个任务。