我正在使用TPL数据流块来处理消息流。我的数据流网络由两个块组成,分别是BufferBlock和ActionBlock,该操作块定义为:
_actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 4,
});
如果操作块内发生错误,我想让故障继续传播并退出应用程序。稍后,我计划在此处添加逻辑以处理瞬态错误,但目前,任何错误都应导致应用程序退出并显示错误详细信息。为此,我添加了一个这样的ContinueWith部分:
_actionBlock
.Completion
.ContinueWith(dbt =>
{
var inner = dbt.Exception.InnerExceptions.First();
throw inner;
},
TaskContinuationOptions.OnlyOnFaulted
);
问题在于“ throw inner”不会传播到任何地方,应用程序只是在继续执行,就好像吞没了异常一样。我的代码中没有其他的异常处理程序。作为实验,我尝试了
使用
重新引发异常 Dispatcher.CurrentDispatcher.Invoke(() => throw ...)
检查ContinueWith内容是否在UI线程上运行。
使用以下方法处理所有顶级异常:
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(ToplevelHandler);
(引发的异常永远不会到达TopLevelHandler)
这些都没有帮助。
如何使在ContinueWith函数中引发的异常传播到应用程序的顶部,并使应用程序退出并显示错误消息?
答案 0 :(得分:2)
C#Cookbook中的并发引用(Stephen Cleary):
要从数据流块中捕获异常,请等待其完成 属性。 Completion属性返回一个将完成的任务 当块完成时,如果块发生故障,则完成任务也会发生故障。
actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 4,
});
await actionBlock.Completion;