C# 具有永久任务/线程的TPL数据流块

C# 具有永久任务/线程的TPL数据流块,c#,.net,task-parallel-library,scheduled-tasks,tpl-dataflow,C#,.net,Task Parallel Library,Scheduled Tasks,Tpl Dataflow,Stepen Toub在本文中提到,*块会在项目被推送到其传入队列时创建一个任务。如果计算了队列中的所有项,则任务将被销毁 如果我使用大量块来构建网格,那么实际运行的任务数量不清楚(如果TaskScheduler是默认的,那么活动ThreadPool线程的数量也不清楚) tpldataflow提供了一种方式,我可以说:“好的,我想要这种具有永久运行任务(线程)的块?TL;DR:没有办法将线程专用于块,因为它显然与TPL数据流的目的相冲突,除非通过实现您自己的TaskScheduler。在尝试改进

Stepen Toub在本文中提到,
*块
会在项目被推送到其传入队列时创建一个任务。如果计算了队列中的所有项,则任务将被销毁

如果我使用大量块来构建网格,那么实际运行的任务数量不清楚(如果
TaskScheduler
是默认的,那么活动
ThreadPool
线程的数量也不清楚)


tpldataflow提供了一种方式,我可以说:“好的,我想要这种具有永久运行任务(线程)的块?

TL;DR:没有办法将线程专用于块,因为它显然与
TPL数据流的目的相冲突,除非通过实现您自己的
TaskScheduler
。在尝试改进应用程序性能之前,请进行测量


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

如果项目被推送到传入队列,则创建任务。如果队列中的所有项目都被计算,则任务将被销毁

也许我遗漏了什么,但Stephen所说的只是:[开始时]我们有一个常见的
生产者-消费者
问题,这可以用.Net 4.0堆栈轻松实现,但问题是如果数据用完,消费者就会离开循环,永远不会返回

[之后]Stephen解释了如何使用
TPL Dataflow
解决这个问题,他说
ActionBlock
启动a
任务
,如果它没有启动。在该任务内有等待的代码(以
async
的方式)对于新消息,释放线程,但不销毁任务

Stephen在解释跨链接块发送消息时也提到了task,他说如果没有要发送的数据,POST任务将淡出。这并不意味着与块对应的任务会淡出,只是一些子任务被用来发送数据,仅此而已

TPL Dataflow
中,告诉块不再有任何数据的唯一方法是:调用它的
Complete
方法或完成任何链接块。之后消费任务将停止,并且在处理完所有缓冲数据后,块将结束其任务

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

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

现在,回到你的话:

实际运行的任务数不清楚
活动线程池线程的数量也不清楚

您是如何评测应用程序的?在调试过程中,您可以轻松地找到和。如果还不够,您可以使用本机Microsoft工具或专用评测器评测应用程序,例如。此类工具包可以轻松地为您提供有关应用程序中发生的情况的信息。

是关于TPL的内部机制的数据流库。作为一种机制,它是非常有效的,并且您不应该真正担心任何开销,除非您的预期吞吐量达到每秒100000条或更多(在这种情况下,您应该搜索将工作负载分块的方法)。即使是粒度非常小的工作负载,使用单个任务处理所有消息与使用专用任务处理每个消息之间的差异也不太明显。
任务
是一个“重”的对象“通常是几百个字节,.NET平台每秒能够创建和回收数百万个这样大小的对象

如果每个
任务都需要自己的专用线程才能运行,这将是一个问题,但事实并非如此。通常使用
ThreadPool
线程执行任务,单个
ThreadPool
线程每秒可能执行数百万个短期任务


我还应该提到,TPL数据流也支持异步lambda(带有
Task
返回类型的lambda),在这种情况下,块基本上不需要执行任何代码。他们只是等待生成的promise样式的任务完成,需要异步等待。

感谢您提供的超级详细的答案。现在事情对我来说更清楚了。