如果我说得对,JoinBlock<T1, T2>
就是&#34; WaitAll&#34; TPL数据流:当你有一个T1和一个T2时,它构建一个Tuple<T1, T2>
并将其传递给下一个块。
是否有&#34; ChoiceBlock<T1, T2>
&#34;,&#34; WaitAny&#34; Dataflow,其中Block<T1>
或Block<T2>
下一步执行?
类似的东西:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
编辑:this answer几乎就是我想要的,我想知道当你有不同类型的消费者时,是否有原生/更优雅的解决方案,并避免所有的铸造和类型( T)检查。
EDIT2:只是为了让它更清晰:这是有效的
var stringCast = new TransformBlock<object,string>(o => (string)o);
var stringTarget = new ActionBlock<string>(m_printAction);
stringCast.LinkTo(stringTarget);
var eventCast = new TransformBlock<object, Event>(o => (Event)o);
var eventTarget = new ActionBlock<Event>(m_addEventAction);
eventCast.LinkTo(eventTarget);
var forwarder = new BufferBlock<object>();
forwarder.LinkTo(stringCast, item => item is string);
forwarder.LinkTo(eventCast, item => item is Event);
forwarder.LinkTo(DataflowBlock.NullTarget<object>());
m_messages.LinkTo(forwarder);
m_events.LinkTo(forwarder);
但它丑陋且效率低下。有更合适的东西吗?
旧的CCR(并发和协调运行时)曾经同时具有Join和Choice,但我无法在TPL Dataflow中找到Choice。我错过了什么吗?
答案 0 :(得分:4)
除了使用Dataflowblock.Choose
MSDN的创意之外。
在您的示例中确实没有做出任何选择:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
前面的块必须不知道它将输出什么类型,导致丑陋的对象类型参数,或者你将不必要地将两个块链接成一个。假设后者对两个不同类型的管道有什么不对?
var buffer1 = new BufferBlock<int>();
var buffer2 = new BufferBlock<string>();
var transform1 = new TransformBlock<int, int>((x) => x);
var transform2 = new TransformBlock<string, string>((x) => x);
buffer1.LinkTo(transform1);
buffer2.LinkTo(transform2);
是否有&#34; ChoiceBlock&#34;,&#34; WaitAny&#34; Dataflow,其中
Block<T1>
或Block<T2>
下一步执行?
在任何时候,如果输出在任何一个源(即缓冲区)都可用,则它可用于Block<int>
或Block<string>
。这是不是以打字方式填写了WaitAny隐含合约?
不一定是对OP问题的回答,但对于评论来说太长了。