c# - 具有永久任务/线程的 TPL 数据流 block

标签 c# .net task-parallel-library scheduled-tasks tpl-dataflow

Stepen Toub 在本文中提到 Channel 9 Video那一个*Block如果一个项目被推送到其传入队列,则创建一个任务。如果队列中的所有项目都已计算,则任务将被销毁。

如果我使用大量 block 来构建网格,则实际运行的任务数量不清楚(如果 TaskScheduler 是默认值,则事件 ThreadPool 线程的数量也不清楚)。

TPL Dataflow提供了一种方式,我可以说:“好吧,我想要这种带有永久运行任务(线程)的 block ?

最佳答案

TL;DR:没有办法将线程专用于一个 block ,因为这显然与 TPL Dataflow 的目的相冲突,除非实现您自己的 TaskScheduler。在尝试提高应用程序性能之前先进行测量。


我刚刚看了视频,但找不到这样的短语:

creates a task if an item was pushed to its incoming queue. If all items in queue are computed the task gets destroyed.

也许我遗漏了一些东西,但斯蒂芬所说的是:[在一开始]我们有一个常见的生产者-消费者问题,可以使用.Net 4.0堆栈轻松实现,但是问题是,如果数据用完,消费者就会退出循环,并且永远不会返回。

[之后]Stephen 解释了如何使用 TPL Dataflow 解决此类问题,他说 ActionBlock 启动 Task(如果尚未启动)。该任务内部有一段代码等待(以异步方式)新消息,释放线程,但不会销毁任务。

斯蒂芬在解释跨链接 block 发送消息时也提到了任务,他说如果没有数据要发送,发布任务就会消失。这并不意味着该 block 对应的任务会消失,而只是某个子任务被用来发送数据,仅此而已。

TPL数据流中,向 block 表明不再有数据的唯一方法:通过调用它的Complete方法或完成任何链接的 block 。之后消耗任务将停止,并且在处理所有缓冲数据后,该 block 将结束其任务。

根据TPL Dataflow的官方github, block 内消息处理的所有任务都创建为 DenyChildAttach ,有时还带有 PreferFairness 标志。因此,我没有理由提供一种机制来将一个线程直接安装到 block 中,因为如果 block 中没有数据,它将卡住并浪费 CPU 资源。您可以为 block 引入一些自定义 TaskScheduler,但现在还不清楚为什么需要它。

如果您担心某些 block 可能比其他 block 获得更多的 CPU 时间,有一种方法可以利用这种效果。根据official docs ,您可以尝试设置MaxMessagesPerTask属性,在发送一定量的数据后强制任务重新启动。不过,这应该在测量实际执行时间后完成。

现在,回到你的话:

number of actually running tasks is not clear
the number of active ThreadPool threads is also not clear

您如何分析您的应用程序?在调试过程中您可以轻松找到all active tasksall active threads 。如果这还不够,您可以使用 native Microsoft 工具或专用分析器来分析您的应用程序,例如 dotTrace , 例如。此类工具包可以轻松地为您提供有关应用程序中发生的情况的信息。

关于c# - 具有永久任务/线程的 TPL 数据流 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44465414/

相关文章:

c# - 按可以为 null 的父对象对 IList<Person> 进行排序

c# - 如何避免重复的 Cursor.Current 语句?

c# - 仅某些字符的正则表达式

c# - 使用 .net 生成代码

.net - 如何添加任务优先级功能

c# - XAML 中有没有一种方法可以在双击时选择文本框中的所有文本?

.net - Dotnetnuke版本确定

.net - 通过 float 或decimal 调用参数为 double 的重载函数

c# - 如何使用 yield 在并行 block 或任务中返回 Item 的集合

c# - 为什么在指定状态对象时需要定义一个参数化的lambda表达式?