簡體   English   中英

多播塊 TPL 數據流

[英]Multicast block TPL Dataflow

我需要將一個對象多播到多個路徑中

      producer
         |
      multicast
     |        |
 Process1   Process2
     |        |
   Writedb   WriteFile

廣播塊沒有多大幫助,它只對進程 1 和進程 2 進行最新的處理,如果進程 2 運行晚了,那么它將無法接收消息。

db writer 和 write file 有不同的數據。

這是以下代碼片段。

class Program
{
    public static void Main()
    {
        var broadCastBlock = new BroadcastBlock<int>(i => i);

        var transformBlock1 = new TransformBlock<int, string>(i =>
        {
            Console.WriteLine("1 transformblock called: {0}", i);
            //Thread.Sleep(4);
            return string.Format("1_ {0},", i);
        });

        var transformBlock2 = new TransformBlock<int, string>(i =>
        {
            Console.WriteLine("2 transformblock called: {0}", i);
            Thread.Sleep(100);
            return string.Format("2_ {0},", i);
        });

        var processorBlockT1 = new ActionBlock<string>(i => Console.WriteLine("processBlockT1 {0}", i));
        var processorBlockT2 = new ActionBlock<string>(i => Console.WriteLine("processBlockT2 {0}", i));

        //Linking
        broadCastBlock.LinkTo(transformBlock1, new DataflowLinkOptions { PropagateCompletion = true });
        broadCastBlock.LinkTo(transformBlock2, new DataflowLinkOptions { PropagateCompletion = true });
        transformBlock1.LinkTo(processorBlockT1, new DataflowLinkOptions { PropagateCompletion = true });
        transformBlock2.LinkTo(processorBlockT2, new DataflowLinkOptions { PropagateCompletion = true });

        const int numElements = 100;

        for (int i = 1; i <= numElements; i++)
        {
            broadCastBlock.SendAsync(i);
        }

        //completion handling

        broadCastBlock.Completion.ContinueWith(x =>
        {
            Console.WriteLine("Braodcast block Completed");
            transformBlock1.Complete();
            transformBlock2.Complete();
            Task.WhenAll(transformBlock1.Completion, transformBlock2.Completion).ContinueWith(_ =>
            {
                processorBlockT1.Complete();
                processorBlockT2.Complete();
            });
        });


        transformBlock1.Completion.ContinueWith(x => Console.WriteLine("Transform1 completed"));
        transformBlock2.Completion.ContinueWith(x => Console.WriteLine("Transform2 completed"));
        processorBlockT1.Completion.ContinueWith(x => Console.WriteLine("processblockT1 completed"));
        processorBlockT2.Completion.ContinueWith(x => Console.WriteLine("processblockT2 completed"));


        //mark completion
        broadCastBlock.Complete();
        Task.WhenAll(processorBlockT1.Completion, processorBlockT2.Completion).ContinueWith(_ => Console.WriteLine("completed both tasks")).Wait();


        Console.WriteLine("Finished");
        Console.ReadLine();
    }
}

通過廣播保證交付的最佳方法是什么? 即多播。

我是否應該只在兩端插入兩個緩沖區然后使用它,以便緩沖區始終收集進來的內容,然后該過程可能需要一些時間來處理所有這些內容?

BroadcastBlock保證所有消息都將提供給所有鏈接塊。 所以這正是您所需要的。 不過,您應該解決的是您向BroadcastBlock提供消息的方式:

for (int i = 1; i <= numElements; i++)
{
    broadCastBlock.SendAsync(i); // Don't do this!
}

應該等待SendAsync方法。 您永遠不應有多個針對同一塊的掛起SendAsync操作。 這樣做不僅破壞了對接收消息順序的所有保證,而且內存效率極低。 使用有界塊的全部意義在於通過限制塊的內部緩沖區的大小來控制內存使用。 通過發出多個未等待的SendAsync命令,您可以通過創建一個不完整的Task的外部動態緩沖區來規避這種自我施加的限制,每個任務的權重為數百個字節,用於傳播僅具有此權重的一小部分的消息。 通過首先使塊有界,可以更有效地在內部緩沖這些消息。

for (int i = 1; i <= numElements; i++)
{
    await broadCastBlock.SendAsync(i); // Now it's OK
}

暫無
暫無

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

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