TPL 数据流,是否有 "WaitAny" 的块?
TPL Dataflow, is there a block for "WaitAny"?
如果我没记错,JoinBlock<T1, T2>
是 TPL 数据流的 "WaitAll":当你有一个 T1 和一个 T2 时,它会构建一个 Tuple<T1, T2>
并将其传递给下一个阻止。
是否有Dataflow的"WaitAny"“ChoiceBlock<T1, T2>
”,接下来执行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 几乎是我想要的,我只想知道当你有不同类型的消费者时是否有 native/more 优雅的解决方案,并避免所有的转换和typeof(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。我错过了什么吗?
除了一些真正创意 Dataflowblock.Choose
MSDN.
您的示例中确实没有任何选择:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
前面的块必须不知道它要输出什么类型,导致丑陋的对象类型参数,否则你会link不必要地进入两个块一。假设后者,两个不同类型的管道有什么问题?
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);
Is there a "ChoiceBlock", the "WaitAny" of Dataflow, where either a Block<T1>
or a Block<T2>
are executed next?
在任何时候,如果任一源(即缓冲区)的输出变得可用,则它可用于 Block<int>
或 Block<string>
。这不是以类型化的方式完成 WaitAny 隐含合同吗?
不一定是 OP 问题的答案,但评论时间太长。
如果我没记错,JoinBlock<T1, T2>
是 TPL 数据流的 "WaitAll":当你有一个 T1 和一个 T2 时,它会构建一个 Tuple<T1, T2>
并将其传递给下一个阻止。
是否有Dataflow的"WaitAny"“ChoiceBlock<T1, T2>
”,接下来执行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 几乎是我想要的,我只想知道当你有不同类型的消费者时是否有 native/more 优雅的解决方案,并避免所有的转换和typeof(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。我错过了什么吗?
除了一些真正创意 Dataflowblock.Choose
MSDN.
您的示例中确实没有任何选择:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
前面的块必须不知道它要输出什么类型,导致丑陋的对象类型参数,否则你会link不必要地进入两个块一。假设后者,两个不同类型的管道有什么问题?
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);
Is there a "ChoiceBlock", the "WaitAny" of Dataflow, where either a
Block<T1>
or aBlock<T2>
are executed next?
在任何时候,如果任一源(即缓冲区)的输出变得可用,则它可用于 Block<int>
或 Block<string>
。这不是以类型化的方式完成 WaitAny 隐含合同吗?
不一定是 OP 问题的答案,但评论时间太长。