我可以制作 TPL DataFlow BatchBlock 单例吗?
Posted
技术标签:
【中文标题】我可以制作 TPL DataFlow BatchBlock 单例吗?【英文标题】:Can I make TPL DataFlow BatchBlock Singleton? 【发布时间】:2018-02-17 13:19:07 【问题描述】:我能找到的所有示例都表明我必须调用 .Complete() 才能将消息推送到下一个节点,我想知道如果我制作 BatchBlock Singlton,并让它连续接收消息,自动将消息推送到下一个块消息达到批量大小?以这种方式使用 BatchBlock 有什么缺点吗?
【问题讨论】:
不,您不需要调用.Complete()
,除非您的消息少于 条消息比批量大小。当您完成您的工作并想要关闭管道时,您在 root 块上调用Complete()
。完成将传播到块并使其将任何剩余的消息推送到下一步。
【参考方案1】:
这个问题有点奇怪,因为您不必每次都必须创建一个新的批处理块。您创建 一个 实例并向其发送消息。这就是所有教程和示例所显示的内容。
假设您要读取文件并将内容发送到数据库。您可以使用一个块来读取文件内容,另一个块用于批处理记录,最后一个块一次将数据发送到数据库。这看起来像这样:
var readerBlock=new TransformManyBlock<string,string>(path=>File.ReadLines(path));
var batchBlock=new BatchBlock<string,string>(500);
var dbBlock = new ActionBlock<string[]>(batch=>MyBulkInsertMethod(batch);
var linkOptions = DataflowLinkOptionsPropagateCompletion=true;
readerBlock.LinkTo(batchBlock,linkOptions);
batchBlock.LintTo(dbBlock,linkOptions);
//Start pumping files
forech(var file in Directory.EnumerateFiles(someFolder)
readerBlock.Post(file);
//Finished pumping, tell the reader
readerBlock.Complete();
//Wait untile all messages reach the database block and get processed
await dbBlock.Completion;
您必须明确指定当一个块完成时,其链接的块也将完成。这就是PropagateCompletion
所做的。虽然这对于简单的管道来说似乎是一个奇怪的选择,但 TPL 数据流用于创建任意复杂的步骤网格。在这种情况下,您希望能够明确控制要完成的内容。
一旦我们将所有文件泵送到第一个块readerBlock
,我们就会告诉它我们已经完成了。当该块完成处理时,它将向管道中的 next 块发出信号。
BatchBlock 仅在批处理完成时发送消息,在这种情况下,当它收集 500 行时。 final 批处理可能包含更少的行。如果不调用Complete()
,它将永远不会被发送。不过,使用PropagateCompletion
,完成将传播到 BatchBlock 并使其将剩余部分发送到下一个块。
最后,我们在最后一个区块上await
Completion
任务,确保所有消息都写入数据库
【讨论】:
您实际上并没有在任何地方使用linkOptions
。该选项在哪里?
致每个LinkTo
电话以上是关于我可以制作 TPL DataFlow BatchBlock 单例吗?的主要内容,如果未能解决你的问题,请参考以下文章