2017-05-04 1 views
4

내 응용 프로그램에서 여러 문자열을 대체 값 사전으로 조인하려고합니다.단일 결과를 다른 여러 결과와 결합하는 데이터 블록

readTemplateBlock은 FileInfos와 함께 제공되고 그 내용을 문자열로 반환합니다.
getReplacersBlock은 하나의 대체 단어 사전으로 피드됩니다 (한 번).
joinTemplateAndReplacersBlockreadTemplateBlock의 각 항목에 하나의 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

당신은을 사용하여 고려 가지고 현재의 코드를 가정

이 같은 (C# 7을 사용하고 간결함을 위해 System.ValueTuple 패키지)를 찾습니다 'TaskCompletionSource' 대신'WriteOnceBlock'과'JoinBlock'을 사용합니까? – svick

+0

들어 본 적이 없습니다. 연구 –

+0

당신은 정교하고 어쩌면 답변을 할 수 있습니까? –

답변

2

내장 된 데이터 흐름 블록을 사용하여이를 수행하는 방법을 알 수 없습니다. 대안은 내가 볼 수 있습니다

  1. 그것에 가치를 보내는 유지하는 Task와 함께 작은 BoundedCapacityBufferBlock를 사용합니다. 정확히 어떻게는 Task는 값이 다를 수 나올까요,하지만 당신은 WriteOnceBlock를 좋아하는 경우에, 당신은 다시 그것을 캡슐화 수 : 당신은 다음 CreateWriteOnceRepeaterBlock<IDictionary<string, string>>() 대신 new WriteOnceBlock<IDictionary<string, string>>(null)을 사용

    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); 
    } 
    

    .

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

    대신 사용합니다 :

    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와 함께 갔다. 많은 일을 훨씬 간단하게 만들었습니다. –

관련 문제