我正在使用任务并行库来设置一系列任务,如下所示,但我得到一个奇怪的异常处理经验,我不明白。
我使用Parallel.ForEach并调用一个包含对以下方法的调用的Action。这个Parallel.ForEach包含在try ... catch(AggregateException)中,当发生异常时 - 就像在其中一个Parallel分支中一样 - 一个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);
答案 0 :(得分: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
。但这并没有解决“消失”异常的问题。为了解决这个问题,我看到了两种可能性: