我可以制作TPL DataFlow BatchBlock Singleton吗?

时间:2017-09-08 15:03:32

标签: task-parallel-library tpl-dataflow dataflow

我可以找到的所有示例都显示我必须调用.Complete()来将消息推送到下一个节点,我想知道如果我制作BatchBlock Singlton,并让它连续收到消息,自动将消息传递到下一个块时messasges到达batchsize?这种方式使用BatchBlock有什么缺点?

1 个答案:

答案 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任务,以确保所有消息都写入数据库