【问题标题】:TPL Dataflow, Exception in block fault handler does not propagateTPL 数据流,块故障处理程序中的异常不会传播
【发布时间】:2018-11-20 14:06:28
【问题描述】:

我正在使用 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
            );

问题是“抛出内部”不会传播到任何地方,应用程序只是继续进行,就好像异常被吞噬了一样。我的代码中没有任何其他异常处理程序。作为一个实验,我已经尝试过

  • 使用

    重新抛出异常
       Dispatcher.CurrentDispatcher.Invoke(() => throw ...)
    
  • 检查 ContinueWith 内容是否在 UI 线程上运行。

  • 使用以下方法处理任何顶级异常:

    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(ToplevelHandler);
    

(抛出的异常永远不会到达TopLevelHandler)

这些都没有帮助。

如何使我在 ContinueWith 函数中抛出的异常传播到应用程序的顶部并让应用程序退出并显示错误消息?

【问题讨论】:

  • 当你 throw inner 时,你需要 await Task 在某个时候传播异常。
  • _actionBlock 运行时间很长。我在应用程序启动时创建它,并且在正常情况下它会在应用程序的整个过程中持续运行。代码中没有一个自然点可以让我在不阻塞所有内容的情况下等待它的完成任务。
  • 不幸的是,这就是异常结束的地方。但在那种情况下,ActionBlock 出现故障,无论如何都不会继续处理。您可以在流程中处理异常,也可以将它们附加到流程的结果中以便在外部处理。
  • @James ActionBlocks 总是长期运行。如果你想在块完成后处理异常,不管是错误完成还是正常完成,你await它。 ContinueWith 只会在 ActionBlock 完成 时运行。
  • @James 至于没有传播的异常,你写的相当于TaskFactory.StartNew(()=&gt;throw new Exception());。如果您不等待该任务,则异常将消失。您希望该错误出现在哪里

标签: c# task-parallel-library tpl-dataflow


【解决方案1】:

引用自 C# Cookbook (Stephen Cleary) 中的并发:

要从数据流块中捕获异常,请等待其完成 财产。 Completion 属性返回一个将完成的任务 当block完成时,如果block出错,Completion任务也会出错。

actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
    new ExecutionDataflowBlockOptions()
    {
        MaxDegreeOfParallelism = 4,
    });
await actionBlock.Completion;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多