TPL数据流,块故障处理程序中的异常不会传播

时间:2018-11-20 14:06:28

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

我正在使用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函数中引发的异常传播到应用程序的顶部,并使应用程序退出并显示错误消息?

1 个答案:

答案 0 :(得分:2)

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

  

要从数据流块中捕获异常,请等待其完成   属性。 Completion属性返回一个将完成的任务   当块完成时,如果块发生故障,则完成任务也会发生故障。

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