TL;DR:没有办法将线程专用于块,因为它显然与 TPL Dataflow 的目的相冲突,除非实现您自己的 TaskScheduler。在尝试提高应用程序性能之前进行测量。
我刚刚看了视频,找不到这样的短语:
如果项目被推送到其传入队列,则创建一个任务。如果队列中的所有项目都计算完毕,则任务将被销毁。
也许我遗漏了一些东西,但斯蒂芬所说的只是:[开头]我们有一个常见的Producer-Consumer 问题,可以用 .Net 4.0 堆栈轻松实现,但问题是如果数据用完,消费者离开循环,永远不会返回。
[在那之后]斯蒂芬解释了如何用TPL Dataflow解决这样的问题,他说ActionBlock开始Task如果没有开始。在该任务中,有代码等待(以async 方式)接收新消息,释放线程,但不破坏任务。
Stephen 在解释跨链接块发送消息时还提到了任务,他说如果没有数据要发送,posting 任务将消失。并不是说block对应的task消失了,只是某个子task被用来发送数据而已。
在TPL Dataflow 中,向块说不会有更多数据的唯一方法是:调用它的Complete 方法或完成任何链接块。在该消费任务将停止之后,并且在处理完所有缓冲数据之后,该块将结束它的任务。
根据TPL Dataflow 的官方 github,块内消息处理的所有任务都创建为DenyChildAttach,有时还带有PreferFairness 标志。所以,我没有理由提供一种机制让一个线程直接适合块,因为如果块没有数据,它会卡住并浪费 CPU 资源。您可能会为块引入一些自定义TaskScheduler,但现在还不清楚为什么需要它。
如果您担心某些块可能比其他块获得更多的 CPU 时间,有一种方法可以利用这种效果。根据official docs,您可以尝试设置MaxMessagesPerTask 属性,在发送一定数量的数据后强制任务重新启动。不过,这应该仅在测量实际执行时间后进行。
现在,回到你的话:
实际运行的任务数量不清楚
活跃的ThreadPool线程数也不清楚
您是如何分析您的应用程序的?在调试过程中,您可以轻松找到all active tasks 和all active threads。如果这还不够,您可以使用本地 Microsoft 工具或专门的分析器(例如 dotTrace)来分析您的应用程序。这样的工具包可以很容易地为您提供有关您的应用程序正在发生的事情的信息。