【发布时间】:2020-05-26 13:33:10
【问题描述】:
我正在使用 TaskParallelLibrary DataFlow 与 Stephen Cleary (https://github.com/StephenCleary/Try) 设计的 Try 库相结合来实现所谓的“铁路编程”,因此我可以将 Exception 数据传递到管道中。我想知道在ActionBlock 中是否有可能获得一些关于什么或(在我的情况下)究竟是哪个项目导致Exception 的上下文?
这是小示例代码:
public async Task TestRailroadException(List<int> constructIds)
{
var downloadBlock = new TransformBlock<int, Try<int>>(
construct => Try.Create(() =>
{
//ThisMethodMyThrowException();
return 1;
}));
var processBlock = new TransformBlock<Try<int>, Try<int>>(
construct => construct.Map(value =>
{
//ThisMethodMyAlsoThrowException();
return 1;
}));
var resultsBlock = new ActionBlock<Try<int>>(construct =>
{
if (construct.IsException)
{
var type = construct.Exception.GetType();
//Here it would be nice to know which item(id) was faulted.
}
});
downloadBlock.LinkTo(processBlock, new DataflowLinkOptions
{ PropagateCompletion = true });
processBlock.LinkTo(resultsBlock, new DataflowLinkOptions
{ PropagateCompletion = true });
foreach (var constructId in constructIds)
{
await downloadBlock.SendAsync(constructId);
}
downloadBlock.Complete();
await resultsBlock.Completion;
}
【问题讨论】:
-
看看这个:AsyncLocal values not correct with TPL Dataflow。 TL;DR
AsyncLocal类不能用于将环境上下文数据与每条消息一起传递。因此,除了使用元组或自定义类或结构作为消息手动将上下文数据从一个块传递到另一个块之外,别无选择。 -
@Theodor。谢谢你的答案。你认为在每个块中捕获错误,添加带有错误项目 id 的
exception.Data,然后重新抛出它们以在resultsBlock中再次捕获它们是个好主意吗?这样我就可以知道是谁造成了exception,而我不必在每个块中重复所有catch逻辑。这不是很漂亮的解决方案,但它可以完成工作。 -
是的,没关系。但是使用 Stephen Cleary 的 Try 库可能会更干净。它在技术上也更优越,除非您愿意了解
ExceptionDispatchInfo类,并使用它而不是裸露的Exception来存储异常。 :-) -
var downloadBlock = new TransformBlock<int, (int, Try<int>)>怎么样?结果是一个ValueTuple,有两个成员,即原始项目及其结果,结果包装在Try中。然后继续将原始项目从一个块传递到另一个块,使用元组作为TInput和TOutput。 -
@Theodor 啊!但是当然!如此简单,却又精彩!谢谢!如果您将此作为答案与一个小样本一起发布,我绝对会接受它!
标签: c# task-parallel-library pipeline tpl-dataflow