2012-11-28 12 views
18

Szukam rozwiązania blokowego przepływu danych TPL, które może pomieścić więcej niż jeden element, który może łączyć się z wieloma blokami docelowymi, ale które ma możliwość przekazania elementu tylko do określonego bloku docelowego, który przekazuje filtr/predykat . W żadnym momencie element nie może być dostarczany do wielu bloków docelowych w tym samym czasie, zawsze tylko do tego, który pasuje do filtru lub element może zostać odrzucony. Nie jestem zwolennikiem BroadCastBlock, ponieważ, jeśli dobrze rozumiem, nie gwarantuje to dostarczenia (lub nie?), A filtrowanie odbywa się po stronie bloku docelowego, co oznacza, że ​​BroadCastBlock zasadniczo wysyła kopie każdego elementu do wszystkich bloków linkedTo target. W każdym razie nie posiada ona więcej niż jednego przedmiotu, jeśli dobrze rozumiem. Nie chcę używać funkcji Post/Async, ale utrzymuję łańcuch LinkTo.TPL Dataflow, jak przekazywać produkty do jednego konkretnego bloku docelowego spośród wielu powiązanych bloków docelowych?

Czy istnieje sposób obejścia całego niestandardowego bloku przepływu danych? Czy nie rozumiem jak działa BroadCastBlock? Niestety nie ma tam zbyt wiele dokumentacji, która zawiera szczegółowe informacje i obejmuje przypadki użycia. Wszelkie pomysły są wysoko cenione.

Odpowiedz

22

Jeśli dobrze cię rozumiem, to, czego chcesz, może być wykonane przez proste BufferBlock, które będzie połączone ze wszystkimi blokami docelowymi z predykatami. Możesz także (bezwarunkowo) połączyć go z numerem NullTarget block, aby odrzucić elementy, które nie pasują do siebie.

Coś jak:

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

W ten sposób, każdy element zostanie wysłany do pierwszego celu, który pasuje, jeśli istnieje.

BroadcastBlock może być przydatny, jeśli chcesz wysłać każdy element do wielu obiektów docelowych lub jeśli chcesz odrzucić elementy, jeśli blok docelowy nie jest wystarczająco szybki.

Z BroadcastBlock, przedmioty mogą zostać usunięte, jeśli żaden blok ich nie zaakceptuje (nawet jeśli mogą je później zaakceptować). Ale nie powoduje to przypadkowego upuszczenia elementów, więc jeśli bloki docelowe nie mają zestawu BoundedCapacity, myślę, że możesz mieć pewność, że otrzymają wszystkie elementy, których nie pomijają (np. Przez użycie predykatu w LinkTo()).

+0

Jak to działa pod względem technicznym? Czy każdy cel został wypróbowany, dopóki nie zostanie dopasowany, a jeśli nie jego zapchanie pamięci, chyba że zostanie przepłukany przez zerowy blok docelowy? I czy kolejność, w której blok docelowy I linkTo najpierw potem ... dalej? –

+3

Tak, każdy cel jest wypróbowywany w sekwencji. Jeśli żaden cel nie pasuje, element pozostanie w bloku bufora. I w tym przypadku zapychanie pamięci nie jest wielkim problemem, zatykając rurociąg. Innymi słowy, oznaczałoby to, że żaden inny element nie zostanie wysłany z tego bloku, dopóki ten problem nie zostanie zaakceptowany przez jakiś cel. Dlatego potrzebny jest blok 'NullTarget'. I tak, kolejność ma znaczenie, dlatego też możesz [określić, czy chcesz dodać lub przedłożyć każdy cel do listy] (http://msdn.microsoft.com/en-us/library/system.threading.tasks .dataflow.dataflowlinkoptions.append.aspx). – svick

+0

Naprawdę jesteś facetem, który idzie do ponownego TDF. Niesamowite. Wielkie dzięki. Czy w dużym stopniu korzystasz z przepływu danych w TPL lub dlaczego masz głęboką wiedzę (między innymi) na temat tej biblioteki? Wspomniałeś wcześniej, że nie jesteś powiązany z zespołem ds. Współbieżności MS. –

6

Znalazłem zaakceptowaną odpowiedź jako niepoprawną. NullTarget należy łączyć z jego orzeczeniem będącym zaprzeczeniem twoich konsumentów. W przeciwnym razie możesz upuścić wiadomości, które chcesz spożywać.

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

Czy mógłbyś wyjaśnić, że wiadomości się zrzucają? Filtr stosuje się po kolei, więc jeśli linkowanie zostało wykonane we właściwej kolejności, nie ma możliwości odrzucenia ważnej wiadomości, prawda? – VMAtm

+0

@VMAtm W końcu czy kolejność linków przebiega według kolejności? Po prostu chcę się upewnić ... –

+0

@ b.ben Tak, to działa tak – VMAtm

Powiązane problemy