簡體   English   中英

無限並行運行多次相同的ActionBlock

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

我正在學習TPL Dataflow,我已經通過我的一些朋友看到了它的強大功能,並且在實現過程中遇到了問題。

我想要/需要的是盡快發送消息。 我正在用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嗎? 我將繼續研究尋找答案,任何指針將不勝感激。 謝謝!

首先,關於術語的注釋:TPL(任務並行庫的縮寫)與TPL Dataflow不同,它只是一個子集。 TPL總體上包括Parallel.For()Task類型。

現在,您的代碼存在的問題是您太早完成了loadMessage塊。 調用Complete() ,該塊將不再接受任何消息,因此您發布到bufferBlock的消息將永遠不會到達loadMessage

您需要的是僅在bufferBlock將所有消息發送給它之后bufferBlock完成loadMessage 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. 我想要/需要的是盡快發送消息:

    為此,您需要同時向緩沖區發送數據或從緩沖區接收數據。 以下是代碼段:

     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鏈接。

  2. 我的理解是,TPL將比Parallel.For更快。

    這是不正確的,因為它們使用相同的基礎結構。 它們屬於同一個名稱空間System.Threading.Tasks

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM