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

时间:2016-07-14 06:54:11

标签: c# .net hangfire

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

7 个答案:

答案 0 :(得分:22)

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

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

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

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

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:5)

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

shutdown -I

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

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

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

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

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

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

答案 3 :(得分:1)

不确定何时支持此功能,但在带有Hangfire 1.7.0的ASP.NET Core 2.0中尝试了此功能。以下代码每20秒调度一次作业:

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

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

Hangfire仪表板还很好地显示了两次运行之间的较小时间间隔:

Hangfire dashboard

答案 4 :(得分: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来避免一些并发冲突。

答案 5 :(得分:0)

我有一个类似的要求,因为我有一个周期性的工作,需要每15秒运行一次。 为了避免此限制,我所做的只是延迟计划作业的创建(间隔为1分钟),这似乎可以解决问题。 但是,我发现,考虑到轮询间隔(将调度轮询间隔设置为我的频率)和上新工作的延迟,这并不总是应有的准确性,但此刻正在解决问题。但是,更好/合适的解决方案将是好的。

必须解决以下问题,感觉有点肮脏,但这帮助了我... 因此,实质上,我创建了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();    
...

答案 6 :(得分:0)

我必须做同样的事情,但要花5秒。默认的计划轮询间隔设置为15s。因此,完成5秒间隔的工作需要2个步骤。

在Startup.cs中

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

app.UseHangfireDashboard();
app.UseHangfireServer(options);

您的工作

RecurringJob.AddOrUpdate(() => YourJob(), "*/5 * * * * *");