Hangfire在一分钟内重复执行任务

问题描述 投票:13回答:6

有没有办法每隔几秒设置一次篝火重复工作?我不寻求一个解决方案,其中火灾和忘记任务会创造另一个火灾和忘记任务,如果没有,建议的替代方案是什么?

c# .net hangfire
6个回答
5
投票

对于重复性工作,Hangfire不支持不到一分钟的时间间隔。

为什么?想象一下,如果他们允许不到一分钟:让我们说1秒。 hangfire检查数据库中重复出现的作业的频率是多少?这会导致很多数据库IO。

有关更多信息,请参阅Hangfire上的this discussion


23
投票

我认为任何反对允许重复触发不到1分钟的人都是短视的。毕竟,55秒的效率是否低于1分钟?看起来很武断!尽管我喜欢Hangfire,但我遇到的情况是我不得不将客户端引导到Quartz.net,因为业务需要每55秒或类似地运行一次。

任何提出反驳论点的人,如果它被配置为每1秒运行一次就会对性能产生严重影响,那么再次对事物采取封闭的看法。当然,间隔1秒的触发器可能不是一个好主意,但是对于不太可能出现1秒钟的情况,我们是否会放弃55秒或45秒?

在任何情况下,性能都是主观的并且取决于主机平台和硬件。在性能方面,实际上不需要API来强制执行意见。只需使轮询间隔和触发重复可配置。这样,用户可以为自己确定最佳结果。

虽然可以选择将作业编排为每55秒运行一次的后台处理,但这并不十分令人满意。在这种情况下,通过Hangfire UI无法看到该过程,因此它对管理员是隐藏的。我觉得这种做法正在绕开Hangfire的主要好处之一。

如果Hangfire是Quartz.net之类的重要竞争者,它至少会匹配他们的基本功能。如果Quartz可以支持间隔低于1分钟的触发器而不是为什么不能Hangfire!


6
投票

尽管Hangfire不允许您在不到一分钟的时间内安排任务,但实际上可以通过让函数递归调度自身来实现这一点。也就是说,你想要一个方法每2秒就能命中一次,你可以安排一个在Startup上调用方法的后台作业;

BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));

然后在您的PublishMessage方法中执行您的工作,然后安排作业调用相同的方法;

public void PublishMessage()
    {
        /* do your stuff */

        //then schedule a job to exec the same method
        BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));
    }

你需要覆盖的另一件事是默认的SchedulePollingInterval为15s,否则你的方法只会在每15秒后被击中。为此,只需在启动时将BackgroundJobServerOptions的实例传递给UseHangfireServer,就像这样;

var options = new BackgroundJobServerOptions
        {
            SchedulePollingInterval = TimeSpan.FromMilliseconds(2000)
        };

        app.UseHangfireServer(options);

我不知道我的解决方案是多么“万无一失”,但我设法用它来实现我的目标,一切都在生产中“快乐”。


4
投票

不确定何时获得支持,但在使用Hangfire 1.7.0的ASP.NET Core 2.0中进行了尝试。以下代码每20秒调度一次作业:

RecurringJob.AddOrUpdate<SomeJob>(
    x => x.DoWork(),
    "*/20 * * * * *");

如果我没有弄错的话,由于Hangfire使用NCrontab而支持6个令牌(而不是标准的5个令牌),这允许使用6个令牌的cron表达式(第二个粒度而不是分钟粒度)。

Hangfire仪表板也很好地显示了运行之间的小时间间隔:

Hangfire dashboard


0
投票

我遇到了同样的问题,这是我的解决方案:

private void TimingExecuteWrapper(Action action, int sleepSeconds, int intervalSeconds)
{
    DateTime beginTime = DateTime.UtcNow, endTime;
    var interval = TimeSpan.FromSeconds(intervalSeconds);
    while (true)
    {
        action();
        Thread.Sleep(TimeSpan.FromSeconds(sleepSeconds));
        endTime = DateTime.UtcNow;
        if (endTime - beginTime >= interval)
            break;
    }
}

intervalSeconds是最小的NCRON间隔。这是1分钟。行动是我们的工作代码。另外我建议使用DisableConcurrentExecution来避免一些并发冲突。


0
投票

我有类似的要求,因为我有一个需要每15秒运行一次的重复工作。我试图绕过这个限制所做的只是延迟创建预定的作业(设置为1分钟间隔),这似乎可以解决问题。然而,我发现,考虑到轮询间隔(将schedulepolling间隔设置为我的频率)和延迟拾取新作业,这并不总是如此准确,但是暂时正在做的伎俩。然而,更好/适当的解决方案将是好的。

感觉有点脏,不得不解决下面的方法,但它帮助我...所以本质上我创造了4个工作做同样的事情,创造了相隔15秒。沿着:

...

new Thread(() =>
{
    //loop from {id=1 through 4}
    //   create job here with {id} in the name at interval of 1 minute
    //   sleep 15 seconds
    //end loop
}).Start();    
...
© www.soinside.com 2019 - 2024. All rights reserved.