2017-12-26 5 views
2

오픈 소스 라이브러리 DataflowEx을 다음 Dataflow 선언과 함께 사용하려고합니다. AAAA 18 | 54.3773 : 32 : 32 : 나는DataflowEx가 완료되지 않음

var requestClientFlow = new RequestClientFlow(this); 
requestClientFlow.Post(""); 
requestClientFlow.Complete(); 
await requestClientFlow.InputBlock.Completion; 

이 완료 내 출력 표시

(18)처럼 소비

class RequestClientFlow :Dataflow<string>{ 
    private readonly ILogger _logger; 
    private readonly Dataflow<string, WebProxy> _webproxyDataflow; 
    private readonly Dataflow<WebProxy, HttpClient> _httpClientDataflow; 

    public RequestClientFlow(ILogger logger) : this(DataflowOptions.Default){ 
     _logger = logger; 
    } 

    public Dataflow<WebProxy, HttpClient> HttpClientDataflow => _httpClientDataflow; 

    public RequestClientFlow(DataflowOptions dataflowOptions) : base(dataflowOptions){ 
     _webproxyDataflow = new TransformBlock<string,WebProxy>(s => { 
      _logger.WriteLine("aaaa"); 
      return new WebProxy(); 
     }).ToDataflow(); 
     _httpClientDataflow = new TransformBlock<WebProxy,HttpClient>(proxy => { 
      _logger.WriteLine("bbbb"); 
      return new HttpClient(); 
     }).ToDataflow(); 
     _webproxyDataflow.LinkTo(_httpClientDataflow); 
     RegisterChild(_webproxyDataflow); 
     RegisterChild(_httpClientDataflow); 
    } 

    public override ITargetBlock<string> InputBlock => _webproxyDataflow.InputBlock; 
} 

54.3773 | BBBB

1 통과, 0 실패, 0 생략, 1.45 초 (xUnit.net 2.3.1 빌드 3858).

그러나 이해의 나

내가 또한

requestClientFlow.Complete(); 
    await requestClientFlow.CompletionTask; 

하거나 완료되지도

await requestClientFlow.SignalAndWaitForCompletionAsync(); 

을 사용할 수 있어야 프레임 워크 문서에서입니다. 누군가 내가 내가 뭘 잘못했는지 이해하도록 도와 줄 수 있습니까?

답변

1

마지막 블록이 TransformBlock이므로 흐름을 완료 할 수 없습니다. 첫 번째 예에서는 await입력 완료 블록이 실제로 완료됩니다. 출력 블록은 출력 버퍼의 항목이 갈 곳이 없어 완료 할 수 없습니다. DataflowEx 라이브러리는 흐름의 마지막 블록에 올바르게 awaiting입니다. 완성을 위해 ActionBlock 또는 NullTarget을 끝에 추가 할 수 있습니다. DataflowEx의 측면에서

최종 흐름은

public interface IDataflow<in TIn> : IDataflow 
{ 
    ITargetBlock<TIn> InputBlock { get; } 
} 

을 implmeneting되어야 라이브러리 쇼에 대한 github 페이지의 예로서 :

public class AggregatorFlow : Dataflow<string> 
{ 
    //...// 

    public AggregatorFlow() : base(DataflowOptions.Default) 
    { 
     _splitter = new TransformBlock<string, KeyValuePair<string, int>>(s => this.Split(s)); 
     _dict = new Dictionary<string, int>(); 

     //***Note The ActionBlock here*** 
     _aggregater = new ActionBlock<KeyValuePair<string, int>>(p => this.Aggregate(p)); 

     //Block linking 
     _splitter.LinkTo(_aggregater, new DataflowLinkOptions() { PropagateCompletion = true }); 

     /* IMPORTANT */ 
     RegisterChild(_splitter); 
     RegisterChild(_aggregater); 
    } 

    //...// 
} 
+0

흠의 대답에 대한 thnks하지만 얻을 여전히 하드 그것. ActionBlock을 사용하면 변형 된 객체를 다른 재사용 가능한 구성 요소 나 데이터 흐름으로 노출시킬 수 없습니다. DataflowBlock.NullTarget 옵션을 데모 해 주시겠습니까? –

+2

'ActionBlock' 또는'NullTarget'은 생성 된'HttpClient'를 다른 플로우로 넘겨 줄 수 없습니다. 이것이 당신의 요구 사항이라면 당신의 흐름은'Dataflow '일 필요가 있습니다. 그리고 테스트에서'DataflowEx'의'LinkLeftToNull()'을 사용하여 그 흐름을 연결할 수 있습니다. – JSteward

+0

이 예제는 기본 블록에서'ToDataflow()'를 호출하지 않고'DataflowLinkOptions '를 사용하여 내부 블록 사이에서 완료를 명시 적으로 전달한다는 점에 유의하십시오 [# 5 고급 링크] (https://github.com/gridsum/DataflowEx)() {PropagateCompletion = true}' – JSteward

관련 문제