22

TPL DataflowTransformBlockは、入力を変換するための を提供します。例:

var tb = new TransformBlock<int, int>(i => i * 2);

入力が検証テストに失敗した場合など、入力の一部を出力しないことは可能ですか?

var tb = new TransformBlock<InputType, OutputType>(i =>
{
    if (!ValidateInput(i))
    {
        // Do something to not output anything for this input
    }
    // Normal output
}

それが不可能な場合、その目的を達成するための最良のパターンは何ですか?
以下のようなものですか?

BufferBlock<OutputType> output = new BufferBlock<OutputType>();

var ab = new ActionBlock<InputType>(i =>
{
    if (ValidateInput(i)) 
    {
        output.Post(MyTransform(i));
    }
}
4

3 に答える 3

26

これを行う方法にはいくつかのオプションがあります。

  1. Jonが提案したように使用TransformManyBlockし、1つまたは0つのアイテムを含むコレクションを返します。
  2. TransformBlock「値なし」を表す特別な値 (例: null) と共に使用し、withLinkTo()フィルターを使用してそれらを削除します。また、特殊な値を排出するために、フィルターなしでTransformBlockヌル ブロック ( )にリンクする必要があります。DataflowBlock.NullTarget<T>()
  3. これはハックのようなものだと思いますが、 :のTaskベースのコンストラクターを使用することもできます。何かを返したい場合とそうでない場合に使用します。例えば:TransformBlockTask.FromResult()null

    new TransformBlock<int, int>(i => i % 2 == 0 ? Task.FromResult(i * 2) : null)
    
于 2012-10-31T20:47:56.890 に答える
12

私自身は DataFlow を使用したことはありませんが、 を使用して、各ステップが空のコレクションまたは単一のアイテムを返すようにすることができると思います。TransformManyBlock

var tmb = new TransformManyBlock<InputType, OutputType>(i =>
{
    if (!ValidateInput(i))
    {
        return Enumerable.Empty<OutputType>();
    }
    ...
    // Or return new[] { outputValue };
    return Enumerable.Repeat(outputValue, 1);
});

FilterBlock<T>これを、フィルター述語だけを持つに一般化して、適切な一致を渡すこともできます( WhereLINQ の場合と同様)。最初はTransformManyBlock上記のように使用してこれを実装できますが、後でより効率的にすることができます。

于 2012-10-31T18:01:03.363 に答える
6

少し古い質問です。ここでいくつかの経験を追加したいと思います。データのBufferBlock代わりに を導入し、条件述語で拡張メソッドを使用できるため、有効な値は に進み、無効な値は無視されます。それらを破棄するには、受信したデータを単純に無視するブロックを使用できます。したがって、最終的なコードは次のようになります。ActionBlockLinkToTransformBlockNullTarget

var input = new BufferBlock<int>();
var tb = new TransformBlock<int, int>(i => i * 2);
var output = new BufferBlock<int>();

// valid integers will pass to the transform
input.LinkTo(tb, i => ValidateInput(i));

// not valid will be discarded
input.LinkTo(DataflowBlock.NullTarget<int>());

// transformed data will come to the output
tb.LinkTo(output);

DataflowLinkOptionsまた、リンクは、他のLinkToオーバーロードを使用して調整することもできます。

于 2016-11-04T16:41:27.583 に答える