If I got it correctly, JoinBlock<T1, T2>
is the "WaitAll" of TPL Dataflow: when you have one T1 and one T2, it builds a Tuple<T1, T2>
and passes it to the next block.
Is there a "ChoiceBlock<T1, T2>
", the "WaitAny" of Dataflow, where either a Block<T1>
or a Block<T2>
are executed next?
Something like:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
EDIT: this answer is almost what I want, I'd just like to know if there is a native/more elegant solution when you have consumers of different types, and avoid all the casting and typeof(T) checks.
EDIT2: Just to make it even clearer: this works
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);
But it's ugly and inefficient. Is there something better suited?
The old CCR (concurrency and coordination runtime) used to have both Join and Choice, but I can't find Choice in TPL Dataflow. Am I missing something?
Aside from some really creative use of Dataflowblock.Choose
MSDN.
There really isn't any choice being made in your example:
var choice = new ChoiceBlock<string, int>
res1.LinkTo(choice.Target1);
res2.LinkTo(choice.Target2);
choice.LinkTo(intConsumer);
choice.LinkTo(stringConsumer);
The preceding block would have to not know what type it was going to output, leading to the ugly object type paramter or you would link two blocks unnecessarily into one. Assuming the latter what's wrong with two distinct typed pipelines?
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?
At anytime, if output becomes available at either source, i.e. buffer, its made available to either Block<int>
or Block<string>
. Does this not fullfill the WaitAny implied contract in a typed way?
Not necessarily an answer to the OP question but too long for a comment.