我正在尝试将开源lib DataflowEx与下一个Dataflow声明一起使用。
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;
}
当我像
那样消费它时var requestClientFlow = new RequestClientFlow(this);
requestClientFlow.Post("");
requestClientFlow.Complete();
await requestClientFlow.InputBlock.Completion;
它完成,我的输出显示
18:32:54.3773 | aaaa 18:32:54.3773 | bbbb
1传递,0失败,0跳过,耗时1.45秒(xUnit.net 2.3.1 建立3858)。
但是我的理解来自框架文档,我也应该能够使用
requestClientFlow.Complete();
await requestClientFlow.CompletionTask;
甚至
await requestClientFlow.SignalAndWaitForCompletionAsync();
它没有完成。有人可以帮我理解我做错了吗?
答案 0 :(得分:1)
由于最后一个块是TransformBlock
,您的流量无法完成。在您的第一个示例中,您await
完成输入块,实际上已完成。 输出块无法完成,因为其输出缓冲区中的项目无处可去。 DataflowEx
库在流程的最后一个块上正确awaiting
。您可以在结尾添加ActionBlock
或NullTarget
以实现完成。
就DataflowEx
而言,最终的流程应该是非常重要的
public interface IDataflow<in TIn> : IDataflow
{
ITargetBlock<TIn> InputBlock { get; }
}
正如图书馆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);
}
//...//
}