簡體   English   中英

理解 TPL 數據流並行度排序

[英]Understanding TPL Dataflow Degree of Parallelism ordering

我正在閱讀Dataflow (Task Parallel Library) ,其中有一部分內容是:

當您指定的最大並行度大於 1 時,將同時處理多條消息,因此,消息可能不會按接收順序進行處理。 但是,從塊中輸出消息的順序將是正確排序的。

這意味着什么?

例如,我將操作塊設置為並行度 = 5:

testActionBlock = new ActionBlock<int>(i => Consumer(i),
            new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 5
            });

await Producer();
testActionBlock.Completion.Wait();

我的 Producer() 基本上將數字排隊到塊中:

private async Task Producer()
{
    for (int i=0; i<= 1000; i++)
    {
        await testActionBlock.SendAsync(i);
    }
    testActionBlock.Complete();
}

而我的消費者(i)只是寫出以下幾行:

private async Task Consumer(int i)
{
    if (i == 1)
    {
        await Task.Delay(5000);
    }
    Console.WriteLine(i);
}

這是否意味着 Consumer(2) 將被阻塞,直到 Consumer(1) 完成處理(因為有 5 秒的延遲)? 我測試了代碼,但似乎並非如此。 即使我刪除了 5 秒延遲,我也沒有看到輸出是有序的。

[更新]

bBlock = new BufferBlock<int>(option);

testActionBlock = new ActionBlock<int>(i => Consumer(i),
    new ExecutionDataflowBlockOptions()
    {
        MaxDegreeOfParallelism = 5
    });

bBlock.LinkTo(testActionBlock);

await Producer();
testActionBlock.Completion.Wait();

我的 Producer() 現在將添加到 bBlock:

private async Task Producer()
{
    for (int i=0; i<= 1000; i++)
    {
        await bBlock.SendAsync(i);
    }
    bBlock.Complete();
}

那么,在這種情況下,Consumer(1) 將等待 5 秒,然后 Consumer(2) 才能繼續?

不。您可以將 DoP 視為線程(不完全但簡單的方式來思考它)

所以在 5 時,它會嘗試一次處理 5。 由於#1 需要 5 秒,#2 肯定會先完成。 #3、#4 和 #5 可能也是如此。 甚至可能是 #6(因為 #2 已經完成,DoP 將允許它從 #6 開始)

即使沒有延遲,也不能保證處理的順序。 所以永遠不要依賴他們執行的命令 話雖如此,當您使用消息輸出(打印,因為這是它們執行的順序)時,它們將按照它們進入的順序重新排序,即使它們以任意順序執行。

DataflowBlockOptions類包含一個可配置的屬性EnsureOrdered

獲取或設置一個值,該值指示是否應該對塊的消息處理強制執行有序處理。

這個屬性決定了塊是否會按照收到消息的相同順序輸出處理過的消息,默認情況下是true 因此,像TransformBlockTransformManyBlock這樣產生輸出的塊(實現ISourceBlock<TOutput>接口)在將接收到的消息傳播到它們的目標塊(它們鏈接到的ITargetBlock<TInput>塊)時會保留接收到的消息的原始順序。

EnsureOrdered選項與處理消息的順序無關。 例如,將屬性MaxDegreeOfParallelism設置為值DataflowBlockOptions.Unbounded意味着所有接收到的消息將被安排在到達時立即執行,並且——假設ThreadPool有足夠的可用線程——所有這些消息的執行將立即開始。 EnsureOrdered設置為false的效果是,一旦消息的執行完成,它就有資格向下游傳播,即使之前收到的消息的執行尚未完成。

EnsureOrdered選項對ActionBlock沒有影響,因為這些塊不產生輸出。 它也對BufferBlock沒有影響,因為雖然這些塊產生輸出,但它們不做任何處理,所以不會發生任何可能扭曲它們接收到的消息的原始順序的事情。 簡而言之,此屬性僅對產生輸出和執行處理的塊有效。

暫無
暫無

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

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