2017-08-09 92 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