Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在JoinBlock中,当另一个目标被填充时,接收该目标_C#_.net_Tpl Dataflow - Fatal编程技术网

C# 在JoinBlock中,当另一个目标被填充时,接收该目标

C# 在JoinBlock中,当另一个目标被填充时,接收该目标,c#,.net,tpl-dataflow,C#,.net,Tpl Dataflow,我将JoinBlock连接到WriteOnceBlock,并将BufferBlock连接到目标1和2。我的目标是,每次JoinBlock接收到来自BufferBlock的消息时,它也会请求WriteOnceBlock所持有的值 我的第一个猜测是,我可以向Target2完成事件添加一个ContinueWith委托,但这并不完全正确-我需要附加到一个似乎不存在的填充事件 我还尝试在非贪婪模式下使用连接块作为最后的努力,但这并没有改变输出 我是不是漏掉了什么明显的东西 示例: static void

我将JoinBlock连接到WriteOnceBlock,并将BufferBlock连接到目标1和2。我的目标是,每次JoinBlock接收到来自BufferBlock的消息时,它也会请求WriteOnceBlock所持有的值

我的第一个猜测是,我可以向Target2完成事件添加一个ContinueWith委托,但这并不完全正确-我需要附加到一个似乎不存在的填充事件

我还尝试在非贪婪模式下使用连接块作为最后的努力,但这并没有改变输出

我是不是漏掉了什么明显的东西

示例:

static void Main(string[] args)
    {
        var writeOnceBlockTest = new WriteOnceBlock<int>(i => i);
        var queueBlockTest = new BufferBlock<string>();
        var joinBlockTest = new JoinBlock<int, string>();
        var actionBlockTest = new ActionBlock<System.Tuple<int, string>>(tuple => Console.WriteLine($"I received int {tuple.Item1} and string {tuple.Item2}."));

        writeOnceBlockTest.LinkTo(joinBlockTest.Target1);
        queueBlockTest.LinkTo(joinBlockTest.Target2, new DataflowLinkOptions{PropagateCompletion = true});
        joinBlockTest.LinkTo(actionBlockTest, new DataflowLinkOptions { PropagateCompletion = true });

        writeOnceBlockTest.Post(3);
        queueBlockTest.Post("String1");
        queueBlockTest.Post("String2");
        writeOnceBlockTest.Post(4);
        writeOnceBlockTest.Post(5);
        queueBlockTest.Post("String3");
        queueBlockTest.Post("String4");
        queueBlockTest.Complete();
        Console.ReadLine();
    }
static void Main(字符串[]args)
{
var writeOnceBlockTest=新的WriteOnceBlock(i=>i);
var queueBlockTest=new BufferBlock();
var joinBlockTest=新的JoinBlock();
var actionBlockTest=newactionblock(tuple=>Console.WriteLine($“我收到int{tuple.Item1}和string{tuple.Item2}”);
writeOnceBlockTest.LinkTo(joinBlockTest.Target1);
queueBlockTest.LinkTo(joinBlockTest.Target2,新的DataflowLinkOptions{PropagateCompletion=true});
LinkTo(actionBlockTest,新数据流链接选项{PropagateCompletion=true});
writeOnceBlockTest.Post(3);
queueBlockTest.Post(“String1”);
queueBlockTest.Post(“String2”);
writeOnceBlockTest.Post(4);
writeOnceBlockTest.Post(5);
queueBlockTest.Post(“String3”);
queueBlockTest.Post(“String4”);
queueBlockTest.Complete();
Console.ReadLine();
}
所需输出:

static void Main(string[] args)
    {
        var writeOnceBlockTest = new WriteOnceBlock<int>(i => i);
        var queueBlockTest = new BufferBlock<string>();
        var joinBlockTest = new JoinBlock<int, string>();
        var actionBlockTest = new ActionBlock<System.Tuple<int, string>>(tuple => Console.WriteLine($"I received int {tuple.Item1} and string {tuple.Item2}."));

        writeOnceBlockTest.LinkTo(joinBlockTest.Target1);
        queueBlockTest.LinkTo(joinBlockTest.Target2, new DataflowLinkOptions{PropagateCompletion = true});
        joinBlockTest.LinkTo(actionBlockTest, new DataflowLinkOptions { PropagateCompletion = true });

        writeOnceBlockTest.Post(3);
        queueBlockTest.Post("String1");
        queueBlockTest.Post("String2");
        writeOnceBlockTest.Post(4);
        writeOnceBlockTest.Post(5);
        queueBlockTest.Post("String3");
        queueBlockTest.Post("String4");
        queueBlockTest.Complete();
        Console.ReadLine();
    }
我收到了int 3和String1

我收到了int 3和String2

我收到了int 3和String3

我收到了int 3和String4

实际输出:

static void Main(string[] args)
    {
        var writeOnceBlockTest = new WriteOnceBlock<int>(i => i);
        var queueBlockTest = new BufferBlock<string>();
        var joinBlockTest = new JoinBlock<int, string>();
        var actionBlockTest = new ActionBlock<System.Tuple<int, string>>(tuple => Console.WriteLine($"I received int {tuple.Item1} and string {tuple.Item2}."));

        writeOnceBlockTest.LinkTo(joinBlockTest.Target1);
        queueBlockTest.LinkTo(joinBlockTest.Target2, new DataflowLinkOptions{PropagateCompletion = true});
        joinBlockTest.LinkTo(actionBlockTest, new DataflowLinkOptions { PropagateCompletion = true });

        writeOnceBlockTest.Post(3);
        queueBlockTest.Post("String1");
        queueBlockTest.Post("String2");
        writeOnceBlockTest.Post(4);
        writeOnceBlockTest.Post(5);
        queueBlockTest.Post("String3");
        queueBlockTest.Post("String4");
        queueBlockTest.Complete();
        Console.ReadLine();
    }
我收到了int 3和String1


JoinBlock
在这里不是正确的选择,尽管它看起来确实非常适合。正如您所发现的,
WriteOnceBlock
,只提供一次它的值。但是,您可以多次读取该值。有了它,您可以使用
TransformBlock
来获得所需的行为

public class JoinFlow
{
    [Test]
    public async Task TestWriteOnceBlock()
    {
        var writeOnceBlockTest = new WriteOnceBlock<int>(i => i);
        var queueBlockTest = new BufferBlock<string>();
        var transformBlockTest = new TransformBlock<string, Tuple<int, string>>(async str => Tuple.Create(await writeOnceBlockTest.ReceiveAsync(), str));
        var actionBlockTest = new ActionBlock<Tuple<int, string>>(tuple => Console.WriteLine($"I received int {tuple.Item1} and string {tuple.Item2}."));

        queueBlockTest.LinkTo(transformBlockTest, new DataflowLinkOptions { PropagateCompletion = true });
        transformBlockTest.LinkTo(actionBlockTest, new DataflowLinkOptions { PropagateCompletion = true });

        writeOnceBlockTest.Post(3);
        queueBlockTest.Post("String1");
        queueBlockTest.Post("String2");
        writeOnceBlockTest.Post(4);
        writeOnceBlockTest.Post(5);
        queueBlockTest.Post("String3");
        queueBlockTest.Post("String4");
        queueBlockTest.Complete();
        await actionBlockTest.Completion;
    }
}

这正是我想要的,谢谢!我一直认为我需要调用TargetBlock上的Receive(),该TargetBlock作为参数传入SourceBlock。但是因为JoinBlock上的每个目标上都没有Receive()方法,所以我觉得卡住了。这是完美的!我在使用这个解决方案时遇到了一点问题-希望你能帮助我。无论出于何种原因,转换块在链中的行为都有点奇怪——它不会传播完成信号(尽管在链接上设置了该选项),而且它似乎不会在图形上传递消息。如果删除ReceiveAsync()调用,则其行为符合预期。你知道ReceiveAsync是否有任何副作用可能导致这种行为吗?@setagana这是一种奇怪的行为,
ReceiveAsync
调用本身不会导致这些影响。在回答中的小示例中,
TransformBlock
链接到一个
ActionBlock
Completion
&消息正确传播。可能是由于某种原因,对
await ReceiveAsync
的调用挂起,从而阻止了消息的传播和完成。另一种选择是,很难说出站消息可能阻塞了正常的流。我需要更详细地检查你们的管道,说得更多。“也许一个新问题是最好的解决办法。是的,我也看不出这种行为有什么明显的原因,”JSteward说。我在这里提出了一个单独的问题(有更多细节):