使用Unbounded Parallelism多次运行相同的ActionBlock

时间:2014-02-14 22:01:45

标签: c# multithreading task-parallel-library tpl-dataflow

我正在学习TPL数据流,我已经看到它通过我的一些朋友的力量,我遇到了我的实施问题。

我想要/需要的是尽可能快地发送消息。我在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(); 

问题是loadMessageBlock没有转储上面示例中的消息。我一直在寻找一些运气不佳的见解。我想我错过了TPL的基本功能。我的理解是BufferBlock保存要由其他块处理的信息,而ActionBlocked(链接到BufferBlock)应该从缓冲区中获取数据并执行它需要做的事情。将信息放在缓冲区停止完成的For循环之后,调用停止线程。

在我的实现中,我有一个Parallel.For,它运行我的loadMessage中的代码就好了。我只是无法实现TPL来做我想做的事情,我的理解是TPL将比Parallel.For快。

我是否认为这可以起作用?我错误地使用了TPL吗?我将继续研究答案,任何指针都将受到高度赞赏。谢谢!

2 个答案:

答案 0 :(得分:1)

首先,关于术语的说明:TPL(任务并行库的缩写)与TPL数据流不同,它只是一个子集。 TPL整体包含Parallel.For()Task类型等内容。

现在,您的代码存在的问题是您过早地完成了loadMessage阻止。致电Complete()后,该区块不再接受任何邮件,因此您发布到bufferBlock的邮件将永远不会到达loadMessage

您需要的是仅在loadMessage向其发送所有消息后才完成bufferBlock。这正是PropagateCompletion所做的:

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

// post your data to bufferBlock here

bufferBlock.Complete();
await loadMessage.Completion;

此外,在这种特定情况下,根本不需要bufferBlock,您可以直接将消息发布到loadMessage

  

我的理解是TPL比Parallel.For

更快

我不明白为什么一般来说应该更快。在正常情况下,他们的表现应该具有可比性。所以你应该更好地使用适合你问题的那个,而不是选择一个因为“它更快”。如果你真的非常关心性能,那就用两种方式编写代码并测量哪一个更好。

答案 1 :(得分:-2)

  1.   

    我想要/需要的是尽可能快地发送消息:

    要实现这一点,您需要在缓冲区块中同时发送/接收数据。以下是摘录:

    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);
    

    有关详细信息,请参阅MSDN link

  2.   

    我的理解是TPL比Parallel.For。

    更快

    这不正确,因为它们使用相同的底层结构。它们属于同一名称空间System.Threading.Tasks