如何确保 BatchBlock 已完成

How to ensure BatchBlock has completed

我正在尝试了解如何使用 BatchBlock,因为它似乎是我正在进行的项目所需要的。但是,我特别挂断了一个部分,这就是确保批处理完成的方法。以下面的代码为例。它的批处理大小为 5。向其发布了五个值

using System;
using System.Linq;
using System.Threading.Tasks.Dataflow;

namespace sandbox
{
    class Program
    {

        public static void Main(string[] args)
        {
            BatchBlock<int> batchBlock = new BatchBlock<int>(5);
            ActionBlock<int[]> actionBlock = new ActionBlock<int[]>(OutputAverage);

            batchBlock.LinkTo(actionBlock, new DataflowLinkOptions() { PropagateCompletion = true });

            batchBlock.Post(1);
            batchBlock.Post(2);
            batchBlock.Post(3);
            batchBlock.Post(4);
            batchBlock.Post(5);

            batchBlock.Complete();
            batchBlock.Completion.Wait();
        }

        private static void OutputAverage(int[] values) =>
            Console.WriteLine("The average is: " + values.Average());

    }
}

如果我运行上面的代码,没有任何输出到控制台window。这是因为程序执行在批次有时间处理之前完成。如果我在末尾添加一个超小的 Thread.Sleep(100);,那么这足以延迟它完成批处理并将预期的文本输出到控制台。

我还想到了其他解决方案,包括经典的 Console.ReadLine() 但最终,我需要它成为可以调用和 运行s 直到完成的东西所有批次均已正确处理,无需有人观看并按回车键关闭。

我想使用的实际项目是一个读取大型 (>4GB) 二进制编码文件并一次处理块以解析记录的项目。 BatchBlock 部分将用于批量处理已解析的记录,并在解析的同时将它们输出到 JSON 文件。目前一切都按预期工作,除了我的测试文件,这些文件很小并且只包含 ~400 条记录,程序在批处理线程完成之前退出。

所以最终,我的问题是,我可以做些什么来确保在程序退出之前所有的批处理都已被操作完成?

您需要等待管道中的最后一个块,而不是第一个。只需替换此:

batchBlock.Completion.Wait();

...有了这个:

actionBlock.Completion.Wait();