4

Task Parallel Library を使用して、以下に示すようにタスクのチェーンを設定していますが、理解できない奇妙な例外処理が発生しています。

Parallel.ForEach を使用して、次のメソッドへの呼び出しを含む Action を呼び出します。この Parallel.ForEach は try...catch(AggregateException) にラップされており、例外が発生すると (Parallel ブランチの 1 つで発生するように) 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);
4

1 に答える 1

6

コードを少し単純化しましょう。

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代わりに使用してください。しかし、それでは「消える」例外の問題は解決しません。それを解決するには、次の 2 つの可能性があります。

  1. 各継続の開始時に呼び出しWait()、 any を使用しないでくださいTaskContinuationOptions。これは、 にラップされた例外が発生する可能性があることを意味しAggregateException、それ自体AggregateExceptionが にラップされ、別のにラップされAggregateExceptionます。これを解決するには、Flatten()またはを使用できますHandle()

  2. を使用して、すべてのタスクを待ちTask.WaitAll()ます。元の例外と、最初の例外のためにキャンセルされた各タスクを含むWaitAll()をスローします。AggregateExceptionTaskCanceledException

于 2012-04-04T13:24:42.110 に答える