【问题标题】:TPL dataflow bufferblock message send on a timer在计时器上发送 TPL 数据流缓冲区块消息
【发布时间】:2014-09-02 17:01:26
【问题描述】:

我想以this 问题为基础。

到目前为止,我已经找到了一种并行处理作业的方法。我在控制台应用程序中运行它。我从 db 得到了 50 个工作,使用TPL DataFlow 处理它们,到目前为止一切都很好。但我意识到,如果有一个工作需要一个小时来处理,而其余的工作在 15 分钟内完成,那么控制台应用程序将继续运行一个小时而不处理任何进一步的工作。我无法将其更改为 Windows 服务,因此我必须让控制台应用程序处理新的工作,可能每 15 分钟检查一次。

我可以启动一个计时器,每 15 分钟检查一次新作业。如果数据库中有任何新工作,我需要添加到buffer block 以便actionblock 可以处理它。问题是,在添加前 50 个作业后,您必须调用 complete 和 completion.wait 以获得缓冲区和操作块。所以我不能再向现有缓冲区添加新作业了。

我可以检查当前的actionblock's isCompleted 属性,然后动态创建buffer/actionblock 的另一个组合。基本上条件是如果当前的actionblock 仍在运行,请检查timer 上的新工作并创建一个新的buffer/actionblock 组合。这就是我打算做的。但在我走上这条路之前,有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: c# multithreading timer tpl-dataflow


    【解决方案1】:

    如果我理解正确并且您想要的只是要同时执行的作业的恒定“流”,但等待执行的作业不超过 50 个,您可以使用相同的 ActionBlockBoundedCapacity 并添加可以的话:

    private static Task ProcessJobsAsync(CancellationToken cancellationToken)
    {
        var block = new ActionBlock<Job>(
            job => job.Process(),
            new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = Environment.ProcessorCount, // Or any other value that fits
                BoundedCapacity = 50,
            });
        cancellationToken.Register(block.Complete);
        var producer = Task.Run(async () =>
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                foreach (var job in await GetJobsAsync())
                {
                    await block.SendAsync(job,cancellationToken);
                }
            }
        });
    
        return Task.WhenAll(producer, block.Completion);
    }
    

    如果块很慢,并达到其容量wait block.SendAsync(job,cancellationToken); 将异步等待,直到队列中的空间被清除以用于另一个作业。这样你总是有工作要执行。当您想关闭应用程序(或取消操作)时,您可以使用CancellationToken 发出信号

    【讨论】:

    • 我想我可能不是 100% 清楚。控制台作业每 5 分钟在计时器上运行一次。这个想法是处理新作业,因为它们每次运行最多可用于 50 个作业。有时只需不到 5 分钟即可完成 10 项工作,有时可能是 30 项,有些需要 1 小时。因此,如果一个工作需要一个小时,控制台应用程序将运行一个小时(下一个控制台实例将等到当前完成)。但是,如果只有一个工作需要一个小时并在 15 分钟内完成,我想继​​续检查同一个控制台工作实例中的新工作 - 这就是为什么要使用计时器。
    • 这不是需要执行的固定工作流。控制台作业在处理 50 个(或有多少个可用)后结束,并以一定频率再次唤醒以进行检查。
    • @AlexJ 所以你每 15 分钟运行一次你的应用程序?为什么不只运行一次,它会确保始终处理新项目?
    • 我认为它需要转换为服务,我现在不能这样做。 stackoverflow.com/questions/695877/…
    • @AlexJ 这是一个非常奇怪的设计。假设您剩下一个需要一个小时的工作,因此您添加了更多工作,但随后又添加了另一个需要一个小时的工作,依此类推……那您想做什么?
    猜你喜欢
    • 2021-06-05
    • 2012-10-20
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多