C# TPL数据流缓冲块消息在计时器上发送

C# TPL数据流缓冲块消息在计时器上发送,c#,multithreading,timer,tpl-dataflow,C#,Multithreading,Timer,Tpl Dataflow,我想在这个问题上再接再厉 到目前为止,我已经找到了一种并行处理作业的方法。我在一个控制台应用程序中运行这个。我从db那里得到了50个工作,使用TPL DataFlow处理它们,到目前为止还不错。但我意识到,如果有一个作业需要一个小时来处理,其余的作业在15分钟内完成,那么控制台应用程序将继续运行一个小时,而不处理任何其他作业。我无法将其更改为windows服务,因此我必须让控制台应用程序处理新的作业,可能每15分钟检查一次 我可以启动计时器,每15分钟检查一次新工作。如果数据库中有任何新作业,我

我想在这个问题上再接再厉

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

我可以启动计时器,每15分钟检查一次新工作。如果数据库中有任何新作业,我需要添加到
缓冲块
,以便
操作块
可以处理它。问题是,在添加前50个作业后,必须调用complete和completion.wait,等待缓冲区和操作块。因此,我无法向现有缓冲区添加更多新作业


我可以检查当前
actionblock的
isCompleted属性,然后动态创建另一个
buffer/actionblock的组合。基本情况是,如果当前的
actionblock
仍在运行,请检查
计时器上的新作业,并创建一个新的
缓冲区/actionblock
组合。这就是我计划要做的。但是,在我走这条路之前,有没有其他方法可以解决这个问题呢?

如果我理解正确,并且您只希望有一个并发执行的恒定作业“流”,但等待执行的作业不超过50个。您可以使用相同的
ActionBlock
BoundedCapacity
,并在可以的情况下添加:

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);
}
私有静态任务进程JobsAsync(CancellationToken CancellationToken)
{
var block=新动作块(
job=>job.Process(),
新的ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism=Environment.ProcessorCount,//或适合的任何其他值
边界容量=50,
});
cancellationToken.寄存器(block.Complete);
var producer=Task.Run(异步()=>
{
而(!cancellationToken.IsCancellationRequested)
{
foreach(等待GetJobsAsync()中的var作业)
{
wait block.SendAsync(作业,取消令牌);
}
}
});
返回任务.WhenAll(生产者、区块完成);
}

如果块速度慢,并达到其容量
wait block.SendAsync(作业,取消令牌)
将异步等待,直到队列中为另一个作业清除空间。这样,您总是有作业要执行。当您想关闭应用程序(或取消操作)时,您可以使用
取消令牌发出信号,我想我可能没有100%清除。控制台作业每5分钟在计时器上运行一次。其想法是处理新作业,因为每次运行最多可处理50个作业。有时只需要10份工作,完成时间不到5分钟,有时可能需要30份,有些需要1小时。因此,如果一个作业需要一个小时,控制台应用程序将运行一个小时(下一个控制台实例将等待当前任务完成)。但是,如果只有一个作业需要一个小时,并且休息时间在15分钟内完成,我希望在同一个控制台作业实例中不断检查新作业-这就是为什么需要计时器的原因。需要执行的作业不是恒定的流。控制台作业在处理了50个(或有多少个可用)后结束,并以一定的频率再次唤醒以进行检查。@AlexJ那么您每15分钟运行一次应用程序?为什么不运行它一次,它将确保总是得到新的项目来处理?我认为,然后它需要转换为服务,这是我现在不能做的@亚历克斯:这是一个非常奇怪的设计。让我们假设你只剩下一个需要一个小时的工作,所以你添加了更多,但是你添加了另一个需要一个小时的工作,依此类推。。。那你想做什么?