Dataflow ブロックは .NET 4.5の新しい高パフォーマンス並列処理ライブラリのバックボーンである。そして導入するだけで多くの機能を提供しているが、カスタムブロックが必要になる時があるだろう。 Zlatko Michailov氏は、その処理と経験するかもしれない多くの罠を概説したドキュメントをまとめ上げた。完全なガイドであるカスタムTPLデータフローブロック実装ガイドは、 .NETでの並列プログラミング ブログで入手できるので、この記事では重要な点だけを述べる。
始める前に氏が尋ねるのは、あなたは既存の ITargetBlockとISourceBlockを一緒にくっ付けることだけを考えているかどうかである。もしそうなら、Encapsulate機能が新しい IPropagatorBlockを作成してくれる。この関数は紋切り型のコードのほとんどを無くしてくれるが、それでもターゲットからソースブロックにどのようにメッセージが伝搬されるかを明示的に書く必要がある。
もっとコントロールするためには、ITargetBlock と ISourceBlockを明示的に実装できる。ほとんどの抽象インターフェースと違って、必ずしも全てのメソッドがクラスのpublicインターフェースを実装する際に公開することを意図してはいない。 LinkTo や Completeのようなメソッドは、一般的なコードから呼ばれることを意図しているが、OfferMessage のような他のメソッドは、他のブロックから抽象インターフェースを介してのみ呼ばれるべきである。ガイドのセクション5.1にそれぞれに対する推奨の可視性ルールが記載されている。
次に氏は2つの詳細な例を示している。1つ目が同期フィルターブロックで、2つ目が同期変換ブロックである。かなり紋切り型のコードがあるが、どのようにTPLデータフローが内部で動くかをよく説明している。
氏が非同期ブロックについて話始めると、本当に扱いにくいコードが出てくる。最初からロック階層のようなことを考慮し始めなければならない。氏が推奨するアプローチは、組込みのブロックによって使われているもので、送信、受信、値ロックを有する。
ブロックを完了としてマークするのは、単純な事のように見える。Complete か Faultが呼ばれたらCompletion (完了)プロパティを設定する必要があるだけである。しかし、非同期ブロックを使い始めた途端、このことでさえ難しくなってくる。たとえば、実際にプロパティの設定はロックを保持せず行う必要がある。それはロックがその他の同期コードを起動するかもしれないからである。
別の懸念はメッセージを消費するのをGreedyモードか非Greedyモードのどちらで行うかである。もし非Greedyブロックを使っているなら、同じソースをリスンしている他のターゲットとの衝突を避けるために余分な措置を取る必要がある。
最後に氏はメッセージの提供とターゲットのリンクについて述べている。幸いにもこれはずっと簡単である。全ての操作が同期的に行われるからである。
もっと詳細な情報はDevLabsの TPL Dataflowサイトにある。
InfoQは現在、教育コンテンツセクションで働くライターを募集している。もし TPL Dataflowについてよく知っており、この主題で4~6ページの記事を書くことに興味があるなら Jonathan Allen、jonathan@infoq.comまで連絡して欲しい。