我可以找到的所有示例都显示我必须调用.Complete()来将消息推送到下一个节点,我想知道如果我制作BatchBlock Singlton,并让它连续收到消息,自动将消息传递到下一个块时messasges到达batchsize?这种方式使用BatchBlock有什么缺点?
答案 0 :(得分: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 = DataflowLinkOptions{PropagateCompletion=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 Dataflow用于创建任意复杂的步骤网格。在这种情况下,您希望能够明确地控制完成的内容。
我们将所有文件抽到第一个块后,readerBlock
我们告诉它我们已经完成了。当该块完成处理时,它将发出管道中 next 块的信号。
BatchBlock仅在批处理完成时发送消息,在这种情况下,它收集500行。 最终批次可能包含更少的行。如果Complete()
未被调用,则永远不会发送。但是使用PropagateCompletion
,完成将传播到BatchBlock并使其将剩余部分发送到下一个块。
最后,我们await
最后一个块上的Completion
任务,以确保所有消息都写入数据库