2017-08-09 94 views
2

我有一個BroadcastBlock鏈接到ActionBlock。當我在BroadcastBlockActionBlock上順序呼叫「完成」時,它不起作用。而僅僅在BroadCastBlock上打電話「完成」正在工作。鏈接的DataFlow塊完成不起作用

public class ActionTester 
{ 
    private readonly ActionBlock<int> _action; 
    private readonly BroadcastBlock<int> _input; 

    public ActionTester() 
    { 
     _input = new BroadcastBlock<int>(null); 
     _action = new ActionBlock<int>(i => Process(i)); 

     _input.LinkTo(_action, new DataflowLinkOptions { PropagateCompletion = true }); 
    } 

    public void Post(int i) => _input.Post(i); 

    public async Task Process(int i) 
    { 
     await Task.Delay(2000); 
     Console.WriteLine(i); 
    } 

    public void Complete() 
    { 
     _input.Complete(); 
     _action.Complete(); // When this is removed, program is working as expected 
    } 

    public Task Completion => _action.Completion; 
} 

測試代碼是

static void Main(string[] args) 
{ 
    var actor = new ActionTester(); 

    actor.Post(5); 
    actor.Post(7); 

    actor.Complete(); 
    actor.Completion.Wait(); 

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

_action.Complete()存在(註釋行),碼移動經過actor.Completion.wait()和 「完成」 是越來越顯示。如果我刪除_aciton.Complete(),則顯示的值將正確顯示,然後寫入「完成」。

當數據流塊被鏈接時,我們是否應該只調用根塊的「完成」?將PropagateCompletion設置爲true/false不起作用。

解決方案

通過等待根塊完成

public void Complete() 
{ 
    _input.Complete(); 
    _input.Completion.Wait(); 
    _action.Complete(); 
} 

回答

2

當數據流模塊連接起來,解決了我們應該只調用根塊的「完成」?

是的,這正是你應該做的。

如果你做傳播Completion,那麼你做需要完成自己_actionBlock - 所有從緩衝區中的物品進行處理後,將完成。完成操作塊後,它不會接受任何新消息,因此所描述的行爲是預期的和有效的。

+0

當「PropogateCompletion」設置爲false時,我們不應該在所有鏈接的塊上調用complete嗎?在我的例子中,即使我將PropagateCompletion設置爲false,如果我在鏈接塊上完成另一個調用,它也不起作用。 – Saravanan

+0

如果您在**之前完成第二個塊**,則從第一個到第二個發送所有消息,第二個將放棄所有這些消息。所以,如果你不傳播完成,你需要自己處理它。 – VMAtm