【发布时间】:2014-02-03 17:47:34
【问题描述】:
我正在尝试使用 TPL 数据流来创建管道。到目前为止一切正常,我的管道定义如下(尽管我的问题只是广播公司,submissionSucceeded,submissionFailed):
// Define tasks
var productListingBatchBuffer = new BufferBlock<PostSubmissionState>();
var splitFile = new TransformBlock<PostSubmissionState, PostSubmissionState>(s => SplitFile(s));
var saveFile = new TransformBlock<PostSubmissionState, PostSubmissionState>(s => SaveFile(s));
var postSubmission = new TransformBlock<PostSubmissionState, PostSubmissionState>(s => PostSubmission(s));
var broadcaster = new BroadcastBlock<PostSubmissionState>(state => state);
var submissionSucceeded = new ActionBlock<PostSubmissionState>(s => SubmissionSucceeded(s));
var submissionFailed = new ActionBlock<PostSubmissionState>(s => SubmissionFailed(s));
// Link em up
productListingBatchBuffer.LinkTo(splitFile, new DataflowLinkOptions() { PropagateCompletion = true });
splitFile.LinkTo(saveFile, new DataflowLinkOptions() { PropagateCompletion = true });
saveFile.LinkTo(postSubmission, new DataflowLinkOptions() { PropagateCompletion = true });
postSubmission.LinkTo(broadcaster, new DataflowLinkOptions() { PropagateCompletion = true });
broadcaster.LinkTo(submissionSucceeded, new DataflowLinkOptions() { PropagateCompletion = true }, state => state.PostSucceeded);
broadcaster.LinkTo(submissionFailed, new DataflowLinkOptions() { PropagateCompletion = true }, state => !state.PostSucceeded);
我遇到的问题是异常的传播。因为我的 BroadcastBlock 将其完成(以及任何故障)传播到两个块,所以如果确实发生异常,它会传播到两个块。因此,当我这样做时
Task.WaitAll(submissionSucceeded.Completion, submissionFailed.Completion);
我最终得到一个包含两个异常的聚合异常。现在我能做的最好的就是过滤这些,即:
try
{
Task.WaitAll(submissionSucceeded.Completion, submissionFailed.Completion);
}
catch (AggregateException ex)
{
var uniqueExceptions = new AggregateException(ex.Flatten().InnerExceptions.Distinct());
Console.WriteLine("An exception was thrown.\n{0}", uniqueExceptions.Flatten());
}
但我想知道是否有更好的方法来做到这一点。即如果只发生一个异常,我只希望引发一个异常。我是 Dataflow 的新手,所以只是发现了所有的约定。
【问题讨论】:
-
应该
submissionSucceeded和submissionFailed实际上是单独的块吗?如果您将它们组合成一个检查state.PostSucceeded内部,那将解决问题。 -
是的,很可能,在这种情况下。我实际上可能会这样做。但是,更一般地说,这将在任何时候流分裂时发生。例如,在下面的链接中 - 如果在广播器中引发异常,您最终会在存储处理器中复制它:taskmatics.com/blog/…
标签: c# exception tpl-dataflow