Подтвердить что ты не робот

TPL Dataflow, как пересылать элементы только одному конкретному целевому блоку среди многих связанных целевых блоков?

Я ищу решение блока потока данных TPL, которое может содержать больше одного элемента, который может связываться с несколькими целевыми блоками, но который имеет возможность пересылать элемент только определенному целевому блоку, который передает фильтр/сказуемое. Ни в коем случае предмет должен быть доставлен одновременно на несколько целевых блоков, всегда только на тот, который соответствует фильтру или элементу, может быть отброшен. Я не люблю BroadCastBlock, потому что, если я правильно понимаю, он не гарантирует доставку (или делает это?), И фильтрация выполняется на стороне целевого блока, то есть BroadCastBlock по существу отправляет копии каждого элемента всем связанным целевым блокам. Он также не может содержать более одного элемента в любое время, если я правильно понимаю. Я не хочу использовать Post/Async, но поддерживаю цепочку LinkTo.

Есть ли способ создать полный блок потока данных? Или я не понимаю, как работает BroadCastBlock? К сожалению, на самом деле не так много документации, которая детализируется и охватывает варианты использования. Любые идеи высоко ценятся.

4b9b3361

Ответ 1

Если я правильно вас понимаю, то, что вы хотите, может быть выполнено простым BufferBlock, который будет связан со всеми вашими целевыми блоками с предикатами. Вы также (безоговорочно) свяжете его с NullTarget block, чтобы отменить элементы, которые не совпадали.

Что-то вроде:

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

Таким образом, каждый элемент будет отправлен на первую цель, которая соответствует, если есть.

BroadcastBlock может быть полезна, если вы хотите отправить каждый элемент нескольким целям или если вы хотите отменить элементы, если целевой блок не достаточно быстрый.

С помощью BroadcastBlock элементы могут быть удалены, если ни один блок не принимает их (даже если они могут принять его позже). Но он не отбрасывает предметы наугад, поэтому, если у ваших целевых блоков нет набора BoundedCapacity, я думаю, вы можете быть уверены, что они получат все предметы, которые они не снижают (например, используя предикат в LinkTo()).

Ответ 2

Я нашел принятый ответ неверным. NullTarget должен быть связан с его предикатом, являющимся отрицанием ваших потребителей. В противном случае вы можете удалить сообщения, которые вы хотели бы использовать.

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));