2017-05-04 17 views
4

私のアプリケーションでは、置換値の辞書で複数の文字列を結合したいと考えています。単一の結果を他の複数の結果と結合するデータブロック

readTemplateBlockには、FileInfosが供給され、その内容が文字列として返されます。
getReplacersBlockは、1つの置換え辞書でフィードされます(1回限り)。
joinTemplateAndReplacersBlockreadTemplateBlockの各項目に1つのgetReplacersBlockという結果を結合する必要があります。

私の現在の設定では、私が投稿するファイルごとに同じ置換え辞書を再度投稿する必要があります。

// Build 
var readTemplateBlock = new TransformBlock<FileInfo, string>(file => File.ReadAllText(file.FullName)); 
var getReplacersBlock = new WriteOnceBlock<IDictionary<string, string>>(null); 
var joinTemplateAndReplacersBlock = new JoinBlock<string, IDictionary<string, string>>(); 

// Assemble 
var propagateComplete = new DataflowLinkOptions {PropagateCompletion = true}; 

readTemplateBlock.LinkTo(joinTemplateAndReplacersBlock.Target1, propagateComplete); 
getReplacersBlock.LinkTo(joinTemplateAndReplacersBlock.Target2, propagateComplete); 
joinTemplateAndReplacersBlock.LinkTo(replaceTemplateBlock, propagateComplete); 

// Post 
foreach (var template in templateFilenames) 
{ 
    getFileBlock.Post(template); 
} 
getFileBlock.Complete(); 

getReplacersBlock.Post(replacers); 
getReplacersBlock.Complete(); 

ブロックがありますか?多分私が見落とした設定オプション?

+2

あなたはAを使用して考えがあります'WriteOnceBlock'と' JoinBlock'ではなく、辞書の 'TaskCompletionSource'ですか? – svick

+0

聞いたことがありません。研究 –

+0

あなたは精緻化し、おそらく答えになるでしょうか? –

答えて

2

組み込みのデータフローブロックを使用してこれを行う方法を理解できませんでした。私が見ることができる代替案:

  1. はそれに値を送信し続けるTaskと一緒に小さなBoundedCapacityBufferBlockを使用してください。どのように正確にTaskは値が異なる可能性があり得るんが、あなたがWriteOnceBlockを好きなら、あなたはそれを再利用し、カプセル化することができます:

    static IPropagatorBlock<T, T> CreateWriteOnceRepeaterBlock<T>() 
    { 
        var target = new WriteOnceBlock<T>(null); 
        var source = new BufferBlock<T>(new DataflowBlockOptions { BoundedCapacity = 1 }); 
    
        Task.Run(
         async() => 
         { 
          var value = await target.ReceiveAsync(); 
    
          while (true) 
          { 
           await source.SendAsync(value); 
          } 
         }); 
    
        return DataflowBlock.Encapsulate(target, source); 
    } 
    

    その後、CreateWriteOnceRepeaterBlock<IDictionary<string, string>>()の代わりnew WriteOnceBlock<IDictionary<string, string>>(null)を使用します。

  2. WriteOnceBlockに似たカスタムブロックを作成してください。 the source of WriteOnceBlockの大きさを見ると、これはおそらくあまり魅力的ではありません。

  3. データフローブロックの代わりにTaskCompletionSourceを使用してください。

    void ReplaceTemplateBlockAction(Tuple<string, IDictionary<string, string>> tuple) 
    { 
        var (template, replacers) = tuple; 
        … 
    } 
    
    … 
    
    var getReplacersBlock = new WriteOnceBlock<IDictionary<string, string>>(null); 
    var replaceTemplateBlock = new ActionBlock<Tuple<string, IDictionary<string, string>>>(
        ReplaceTemplateBlockAction); 
    … 
    getReplacersBlock.Post(replacers); 
    

    あなたが代わりに使用します:あなたの現在のコードは(C#7と簡潔にするためSystem.ValueTupleパッケージを使用して)次のようになりますと仮定

    void ReplaceTemplateBlockAction(string template, IDictionary<string, string>>> replacers) 
    { 
        … 
    } 
    
    … 
    
    var getReplacersTcs = new TaskCompletionSource<IDictionary<string, string>>(); 
    var replaceTemplateBlock = new ActionBlock<string>(
        async template => ReplaceTemplateBlockAction(template, await getReplacersTcs.Task)); 
    … 
    getReplacersTcs.SetResult(replacers); 
    
+0

私はtaskcompletionsourceに行ってきました。それは多くの事をもっと簡単にすることが判明した –

関連する問題