【问题标题】:Why TPL Dataflow block.LinkTo does not give any output?为什么 TPL Dataflow block.LinkTo 不提供任何输出?
【发布时间】:2014-12-10 23:57:43
【问题描述】:

我对 TPL 数据流主题很陌生。在 Concurrency in C# 一书中,我测试了以下示例。我不知道为什么没有输出应该是2*2-2=2

static void Main(string[] args)
{
    //Task tt = test();
    Task tt = test1(); 
    Console.ReadLine();
}
static async Task test1()
{
    try
    {
        var multiplyBlock = new TransformBlock<int, int>(item =>
        {
            if (item == 1)
                throw new InvalidOperationException("Blech.");
            return item * 2;
        });
        var subtractBlock = new TransformBlock<int, int>(item => item - 2);
        multiplyBlock.LinkTo(subtractBlock,
        new DataflowLinkOptions { PropagateCompletion = true });
        multiplyBlock.Post(2);
        await subtractBlock.Completion;
        int temp = subtractBlock.Receive();
        Console.WriteLine(temp);
    }
    catch (AggregateException e)
    {
        // The exception is caught here.
        foreach (var v in e.InnerExceptions)
        {
            Console.WriteLine(v.Message);
        }

    }

}

Update1:​​我尝试了另一个示例。我仍然没有使用Block.Complete(),但我认为当第一个块完成时,结果会自动传递到第二个块。

private static async Task test3()
{
    TransformManyBlock<int, int> tmb = new TransformManyBlock<int, int>((i) => { return new int[] {i, i + 1}; });
    ActionBlock<int> ab = new ActionBlock<int>((i) => Console.WriteLine(i));

    tmb.LinkTo(ab);

    for (int i = 0; i < 4; i++)
    {
        tmb.Post(i);
    }
    //tmb.Complete();
    await ab.Completion;
    Console.WriteLine("Finished post");
}

【问题讨论】:

    标签: c# tpl-dataflow


    【解决方案1】:

    这部分代码:

    await subtractBlock.Completion;
    int temp = subtractBlock.Receive();
    

    首先(异步)等待减法块完成,然后尝试从该块中检索输出。

    有两个问题:源块永远不会完成,代码正试图从已完成的块中检索输出。一旦一个区块完成,它就不会再产生任何数据了。

    (我假设您指的是配方 4.2 中的示例,它将发布 1,导致异常,从而在错误状态下完成块)。

    因此,您可以通过完成源块来修复此测试(并且完成将沿着链接自动传播到subtractBlock),并在(异步)等待subtractBlock完成之前读取输出:

    multiplyBlock.Complete();
    int temp = subtractBlock.Receive();
    await subtractBlock.Completion;
    

    【讨论】:

    • 我不太明白completing the source block (and the completion will propagate along the link to the subtractBlock automatically 的部分!我发布了一个没有使用 tmb.Complete() 方法的更新,但我确实看到了所有输出。
    • @baozi:一个块的“完成”意味着它完全完成了——它永远不会再发送任何数据。所以数据通过它流向它的目标块直到它完成。完成后,就没有更多数据了。
    • 我可以说对于两个链接的块,只有在第一个块被调用到Complete时,它才能从第二个块接收数据
    • @baozi:如果块A链接到B,B链接到C,那么数据可以一路流过。 Complete 一点也不像“同花顺”;这更像是一种“处置”。
    猜你喜欢
    • 2019-12-23
    • 1970-01-01
    • 2012-01-22
    • 2015-10-22
    • 1970-01-01
    • 2021-09-18
    • 2022-01-10
    • 2023-03-23
    相关资源
    最近更新 更多