2012-11-28 44 views
18

我正在尋找一個TPL數據流塊解決方案,它可以容納多個單個項目,該項目可以鏈接到多個目標塊,但它能夠將項目轉發給僅傳遞過濾器/謂詞的特定目標塊。任何時候都不應該將物品同時交付給多個目標區塊,而是始終只將物品交付給與過濾器相匹配的物品,否則該物品可能會被丟棄。我不喜歡BroadCastBlock,因爲如果我理解正確,它不能保證傳遞(或者是否做到了這一點),並且在目標數據塊端完成過濾,這意味着BroadCastBlock本質上將每個項目的副本發送到所有linkedTo目標模塊。如果我理解正確,它也不會在任何時間持有多個項目。我不想使用Post/Async,但保持LinkTo鏈。TPL Dataflow,如何將項目轉發到許多鏈接的目標塊中只有一個特定的目標塊?

圍繞完整的自定義數據流塊有辦法嗎?或者我誤解了BroadCastBlock的工作原理?不幸的是,真的沒有太多的文檔詳細介紹並涵蓋用例。任何想法都非常感謝。

回答

22

如果我的理解正確,你可以通過一個簡單的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

使用BroadcastBlock,如果沒有塊接受它們(即使它們稍後能夠接受它),則可以刪除項目。但是它不會隨機放置物品,所以如果你的目標街區沒有設置BoundedCapacity,我認爲你可以確定他們會得到所有他們不會拒絕的物品(例如,通過使用LinkTo()中的謂詞)。

+0

這在技術上有效嗎?每個目標是否都嘗試過,直到匹配,如果沒有,則阻塞內存,除非空目標塊被刷新?並且,我首先鏈接到哪個目標塊的順序然後下一個...很重要? –

+3

是的,每個目標都是按順序嘗試的。如果沒有目標匹配,則該項目將保留在緩衝區塊中。在這種情況下,堵塞內存並不是一個大問題,堵塞管道是。換句話說,這意味着沒有其他物品會從這個區塊發出,直到有問題的物品被某個目標接受爲止。這就是爲什麼'NullTarget'塊是必要的。是的,順序很重要,這也是爲什麼你可以[指定是否要將每個目標附加到列表中](http://msdn.microsoft.com/zh-cn/library/system.threading.tasks .dataflow.dataflowlinkoptions.append.aspx)。 – svick

+0

你真的是那個去TDF的人。真棒。非常感謝。您是否廣泛使用TPL數據流或爲什麼該庫的深層知識(包括其他主題)?你之前提到你不隸屬於MS併發團隊。 –

6

我發現接受的答案是不正確的。 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)); 
+0

請您詳細說明丟棄的消息嗎?過濾器按順序應用,因此,如果鏈接按正確的順序完成,則無法刪除有效的消息,對嗎? – VMAtm

+0

@VMAtm那麼最後,按順序連接順序?只是想確保.. –

+0

@ b.ben是的,它的工作原理就像那樣 – VMAtm

相關問題