繁体   English   中英

如何在TPL中实现连续运行的数据流块?

[英]How to implement continuously running dataflow blocks in TPL?

我使用BufferBlock和ActionBlock进行生产者/消费者数据流块设置,它在Console应用程序中运行良好;

将所有项目添加到BurfferBlock并将BufferBlock与其他Action项目链接后; 它运作良好。

现在我想使用内部服务,此数据流块管道将始终处于启动状态,并且当消息通过外部事件可用时,它将进入缓冲区块并开始处理。 我怎样才能做到这一点?

到目前为止,我在下面做了:

public void SetupPipeline()
{
    FirstBlock = new ActionBlock<WorkItem>(new Action<WorkItem>(ProcessIncomingMessage),
    new ExecutionDataflowBlockOptions
    {
        MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
    });

    BufferBlock = new BufferBlock<WorkItem>();

    GroupingDataflowBlockOptions GroupingDataflowBlockOptions = new GroupingDataflowBlockOptions();
    GroupingDataflowBlockOptions.Greedy = true;
    GroupingDataflowBlockOptions.BoundedCapacity = GroupingDataflowBlockOptions.Unbounded;
    CancellationTokenSource = new CancellationTokenSource();
    CancellationToken = CancellationTokenSource.Token;
    GroupingDataflowBlockOptions.CancellationToken = CancellationToken;
    BatchBlock = new BatchBlock<WorkItem>(BoundingCapacity, GroupingDataflowBlockOptions);

    ProcessItems = new ActionBlock<WorkItem[]>(WorkItems =>
        ProcessWorkItems(WorkItems.ToList<WorkItem>()),
        new ExecutionDataflowBlockOptions
      {
          CancellationToken = CancellationToken
      });

    Timer = new Timer(_ =>
            BatchBlock.TriggerBatch()
        );

    TimingBlock = new TransformBlock<WorkItem, WorkItem>(WorkItem =>
    {
        Timer.Change(TimerInterval, Timeout.Infinite);
        logger.Debug("Inside TimingBlock : " + WorkItem.ToString());
        return WorkItem;
    }, new ExecutionDataflowBlockOptions
    {
        CancellationToken = CancellationToken
    });

    BatchBlock.LinkTo(ProcessItems);
    TimingBlock.LinkTo(BatchBlock);
    BufferBlock.LinkTo(TimingBlock);
}

作为一个粗略的过度简化,DataFlow是一种使用一组方法处理大量对象的方法。 它不提供或期望创建这些对象的任何特定方式。

如果您希望管道保持活动状态,请不要终止该应用程序。 如果您不想使用控制台应用程序,请创建一个构建管道的服务,并将对象发送给它直到它关闭。

消息只是您将通过读取数据,响应事件(无论这意味着什么)或任何其他方式创建的对象。

至于外部事件,你是什么意思? 有人会将数据发送到您的应用程序? 有很多方法可以实现:

  • 如果数据来自另一个控制台应用程序,您可以将一个应用程序的结果传递给另一个应用程序,解析来自命令行应用程序的输入流的数据,创建消息并将它们传递给管道
  • 如果您希望服务侦听请求,您可以托管.NET Pipe,WCF或Web API服务来侦听调用并将发布的数据传递给管道。
  • 如果数据来自数据库,您可以轮询更改并将任何已更改的数据发送到管道。

关键是,Dataflow是关于处理数据,而不是关于监听事件。 它不是一个完整的分布式代理系统,如果这是你正在寻找的。

批处理大小由批处理块构造函数中的变量“BoundingCapacity”定义。 批次将在以下时间发布:

  • 收到了一些等于批量大小的帖子(在构造函数中指定)
  • 批次块标记为完成
  • 调用triggerbatch方法

看起来您想要在满足浴槽尺寸或发生超时时发布批次。 如果是这种情况,并且批量大小并不重要,我实际上只是向您拥有的计时器添加一个重复间隔,并使批处理块下游的对象忽略空帖。

您可能真正想要的,以及与数据流编程的理念最相似的是,当您开始发布一系列项目然后在完成或超时发生时完成它时,创建一个新的批处理块。 如果尚不存在,则新帖子将创建新的批处理块。

尝试在仅基于第一个触发器触发的批处理块周围实现超时计时器的问题是,您需要计算并验证缓冲区的帖子,或者您需要查看缓冲区块中的帖子。 这两种情况都会造成很多丑陋和/或违反块封装。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM