c# task-parallel-library actor message-passing tpl-dataflow

c# - Flujo de datos TPL, ¿cómo reenviar elementos a solo un bloque de destino específico entre muchos bloques de destino vinculados?



task-parallel-library actor (2)

He encontrado que la respuesta aceptada es incorrecta. El NullTarget debe vincularse con su predicado como la negación de sus consumidores. De lo contrario, podría soltar los mensajes que deseaba consumir.

var forwarder = new BufferBlock<SomeType>(); forwarder.LinkTo(target1, item => matchesTarget1(item)); forwarder.LinkTo(target2, item => matchesTarget2(item)); forwarder.LinkTo(DataflowBlock.NullTarget<SomeType>(), item => !matchesTarget1(item) && !matchesTarget2(item));

Estoy buscando una solución de bloque de flujo de datos TPL que pueda contener más de un solo elemento, que se pueda vincular a múltiples bloques de destino, pero que tenga la capacidad de reenviar un elemento a solo un bloque de destino específico que pase un filtro / predicado. En ningún momento se debe entregar un artículo a varios bloques de destino al mismo tiempo, siempre solo al que coincida con el filtro o se puede descartar el artículo. No me gusta BroadCastBlock porque, si entiendo correctamente, no garantiza la entrega (¿o sí?) Y el filtrado se realiza en el lado del bloque de destino, lo que significa que BroadCastBlock esencialmente envía copias de cada elemento a todos los bloques de destino enlazados. Tampoco contiene más de un elemento en cualquier momento si lo entiendo correctamente. No quiero usar Post / Async pero mantengo una cadena LinkTo.

¿Hay alguna manera de evitar un bloque de flujo de datos personalizado completo? ¿O no entiendo bien cómo funciona BroadCastBlock? Desafortunadamente, realmente no hay mucha documentación que entre en detalles y cubra los casos de uso. Cualquier idea es muy apreciada.


Si te comprendo correctamente, lo que quieres podría lograrse con un simple BufferBlock , que estaría vinculado a todos tus bloques de destino con predicados. También lo vincularía (incondicionalmente) a un bloque NullTarget , para descartar los elementos que no coincidían.

Algo como:

var forwarder = new BufferBlock<SomeType>(); forwarder.LinkTo(target1, item => matchesTarget1(item)); forwarder.LinkTo(target2, item => matchesTarget2(item)); forwarder.LinkTo(DataflowBlock.NullTarget<SomeType>());

De esta manera, cada elemento se enviará al primer objetivo que coincida, si hay alguno.

BroadcastBlock puede ser útil si desea enviar cada elemento a múltiples objetivos, o si desea descartar elementos si el bloque de destino no es lo suficientemente rápido.

Con BroadcastBlock , los elementos pueden eliminarse si ningún bloque los acepta (aunque pueden ser capaces de aceptarlo más adelante). Pero no suelta elementos al azar, por lo tanto, si sus bloques de destino no tienen establecido BoundedCapacity , creo que puede estar seguro de que obtendrán todos los elementos que no rechazan (por ejemplo, utilizando el predicado en LinkTo() ) .