【发布时间】:2015-11-04 13:11:05
【问题描述】:
我正在设计一个由多个块组成的长期运行的 Dataflow 管道。项目被馈送到管道的输入块,最终通过它,并在最后显示在 UI 中(作为对用户的礼貌——管道的真正工作是将处理结果保存到磁盘)。
管道块中的 lambda 函数可能会抛出异常,原因有很多(输入错误、网络故障、计算过程中的错误等等)。在这种情况下,我不想让整个管道出错,而是踢出有问题的项目,并将其显示在 UI 中的“错误”下。
最好的方法是什么?我知道我可以将每个 lambda 函数包装在 try/catch 中:
var errorLoggingBlock = new ActionBlock<Tuple<WorkItem, Exception>>(...)
var workerBlock = new TransformBlock<WorkItem, WorkItem>(item =>
{
try {
return DoStuff(item);
} catch (Exception ex) {
errorLoggingBlock.SendAsync(Tuple.Create(item, ex));
return null;
}
}
但我在管道中大约有 10 个块,将代码复制/粘贴到每个块中似乎很愚蠢。另外,我不喜欢返回 null 的想法,因为现在所有下游块都必须检查它。
我的下一个最佳想法是创建一个函数,该函数返回一个为我进行包装的 lambda:
private Func<TArg, TResult> HandleErrors<TArg, TResult>(Func<TArg, TResult> f) where TArg:WorkItem
{
return arg =>
{
try {
return f(arg);
} catch (Exception ex) {
errorLoggingBlock.SendAsync(Tuple.Create(item, ex));
return default(TResult);
}
};
}
但这似乎有点太元了。有没有更好的办法?
【问题讨论】:
-
你可以看看 Stephen Cleary 的简约
Try库。它允许通过管道的所有块传递消息,然后观察该消息最后发生的任何异常。
标签: c# error-handling tpl-dataflow