简体   繁体   English

无限并行运行多次相同的ActionBlock

[英]Running the same ActionBlock multiple times with Unbounded Parallelism

I am learning TPL Dataflow, I have seen it's power through some friends of mine and I am running into an issue with my implementation. 我正在学习TPL Dataflow,我已经通过我的一些朋友看到了它的强大功能,并且在实现过程中遇到了问题。

What I want/need is to send messages as fast as I can. 我想要/需要的是尽快发送消息。 I am doing some prototyping in LinqPad and this is what I have thus far: 我正在用LinqPad做一些原型设计,这就是我到目前为止所要做的:

// Holds all the messages for my loadMessage ActionBlock to grab its data from
var bufferBlock = new BufferBlock<string>();

// Sends message to where it needs to go as fast as it can.
var loadMessage = new ActionBlock<string>(msg => 
{
    msg.Dump();
},  
new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});

// Links the blocks together
bufferBlock.LinkTo(loadMessage);

// Loads the Buffer
for (int i = 0; i < 10; i++)
{
    bufferBlock.Post("This is a message");
}

//Calls completion to stop threads
bufferBlock.Complete();
loadMessage.Complete(); 

The problem is that the loadMessageBlock isn't dumping the message in the example above. 问题是在上面的示例中loadMessageBlock没有转储消息。 I have been looking for some insight with little luck. 我一直在寻找一些运气不好的见识。 I think I am missing something fundamental for TPL. 我认为我缺少TPL的一些基本知识。 My understanding is that the BufferBlock holds information to be processed by other blocks, and the ActionBlocked (Which is linked to the BufferBlock) should grab the data off of the buffer and do what it needs to do. 我的理解是,BufferBlock包含要由其他块处理的信息,并且ActionBlocked(与BufferBlock链接)应该从缓冲区中获取数据并执行所需的操作。 After the For loop that puts the information on the buffer stops completion is called to stop the threads. 在将信息放入缓冲区的For循环停止完成之后,将调用以停止线程。

In the implementation I have, I have a Parallel.For that runs the code inside my loadMessage just fine. 在我的实现中,我有一个Parallel.For,可以在我的loadMessage内部运行代码。 I just can't implement TPL to do what I want and my understanding is that TPL will be faster than Parallel.For. 我只是不能实现TPL来做我想做的事,我的理解是TPL将比Parallel.For更快。

Am I way off here in how I think this is suppose to work? 我是否认为我认为该可行? Am I mis-using TPL? 我在滥用TPL吗? I am going to continue to research for an answer, any pointers will be highly appreciated. 我将继续研究寻找答案,任何指针将不胜感激。 Thanks! 谢谢!

First, a note about terminology: TPL (short for Task Parallel Library) is not the same as TPL Dataflow, that's just a subset. 首先,关于术语的注释:TPL(任务并行库的缩写)与TPL Dataflow不同,它只是一个子集。 TPL as a whole includes things like Parallel.For() and the Task type. TPL总体上包括Parallel.For()Task类型。

Now, the problem with your code is that you're completing the loadMessage block too soon. 现在,您的代码存在的问题是您太早完成了loadMessage块。 After you call Complete() , the block won't accept any more messages, so the messages you posted to bufferBlock will never reach loadMessage . 调用Complete() ,该块将不再接受任何消息,因此您发布到bufferBlock的消息将永远不会到达loadMessage

What you need is to complete loadMessage only after bufferBlock sends all its messages to it. 您需要的是仅在bufferBlock将所有消息发送给它之后bufferBlock完成loadMessage Which is exactly what PropagateCompletion does: PropagateCompletion正是这样做的:

bufferBlock.LinkTo(
    loadMessage, new DataflowLinkOptions { PropagateCompletion = true });

// post your data to bufferBlock here

bufferBlock.Complete();
await loadMessage.Completion;

Also, in this specific case, the bufferBlock is not needed at all, you could have just posted the messages directly to loadMessage . 另外,在这种情况下,根本不需要bufferBlock ,您可以将消息直接发布到loadMessage

my understanding is that TPL will be faster than Parallel.For 我的理解是TPL将比Parallel.For更快

I don't see why should be faster in general. 我不知道为什么总体上应该更快。 Under normal circumstances, their performance should be comparable. 在正常情况下,它们的性能应具有可比性。 So you should use the one that fits your problem better, instead of choosing one because “it's faster”. 因此,您应该使用更适合您的问题的解决方案,而不是因为“更快”而选择一种。 And if you really care about performance that much, write the code both ways and measure which one is better. 而且,如果您真的非常在乎性能,那么请以两种方式编写代码并评估哪种更好。

  1. What I want/need is to send messages as fast as I can: 我想要/需要的是尽快发送消息:

    To achieve that, you need to post/ receive data concurrently to and from the buffer block. 为此,您需要同时向缓冲区发送数据或从缓冲区接收数据。 Below is the snippet: 以下是代码段:

     var bufferBlock = new BufferBlock<string>(); // Write to and read from the message block concurrently. var post01 = Task.Run(() => { // Loads the Buffer for (int i = 0; i < 10; i++) { bufferBlock.Post(string.Format("This is a message {0}",i)); } }); var receive = Task.Run(() => { for (int i = 0; i < 10; i++) { var message = bufferBlock.Receive(); message.Dump(); } }); Task.WaitAll(post01, receive); 

    More on this you can see at MSDN link 有关更多信息,请参见MSDN链接。

  2. my understanding is that TPL will be faster than Parallel.For. 我的理解是,TPL将比Parallel.For更快。

    This not correct, because they use the same underlying structure. 这是不正确的,因为它们使用相同的基础结构。 They belong to the same name space System.Threading.Tasks 它们属于同一个名称空间System.Threading.Tasks

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM