c# - TPL 数据流, block 故障处理程序中的异常不会传播

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

我正在使用 TPL 数据流 block 来处理消息流。我的数据流网络由两个 block 组成,一个BufferBlock和一个ActionBlock,其中action block 定义为:

        _actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
            new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 4,
            });

如果操作 block 内发生错误,我想让错误向上传播并退出应用程序。稍后,我计划在此处添加逻辑来处理 transient 错误,但目前,任何错误都应导致应用程序退出并显示故障详细信息。为此,我添加了一个如下的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函数内抛出的异常传播到应用程序顶部并使应用程序退出并显示错误消息?

最佳答案

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

To catch exceptions from a Dataflow block, await its Completion property. The Completion property returns a Task that will complete when the block is completed, and if the block faults, the Completion task is also faulted.

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

关于c# - TPL 数据流, block 故障处理程序中的异常不会传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53394806/

相关文章:

c# - 如果我没有完成ActionBlock会不会有问题

c# - 两个字符串数组的快速 count() 交集

c# - 将锁迁移到 TPL

c# - 如何强制任务在 UI 线程上运行?

c# - Dispatcher.BeginInvoke 和 Task.Factory.StartNew 有什么区别

task-parallel-library - 任务并行库 - 您如何通过 TaskContinuationOptions.OnlyOnCanceled 获得继续触发?

c# - 定义有界容量的贪婪和非贪婪数据流 block 之间的区别

c# - 使用 TPL Dataflow,我可以取消所有帖子然后添加一个吗?

c# - 放置 Database.SetInitializer 的地方

c# - MSTest 将 Mock.Of<IFoo> 列表与 Foo 列表进行比较