有没有办法每隔几秒设置一次篝火重复工作?我不寻求一个解决方案,其中火灾和忘记任务会创造另一个火灾和忘记任务,如果没有,建议的替代方案是什么?
对于重复性工作,Hangfire不支持不到一分钟的时间间隔。
为什么?想象一下,如果他们允许不到一分钟:让我们说1秒。 hangfire检查数据库中重复出现的作业的频率是多少?这会导致很多数据库IO。
有关更多信息,请参阅Hangfire上的this discussion。
我认为任何反对允许重复触发不到1分钟的人都是短视的。毕竟,55秒的效率是否低于1分钟?看起来很武断!尽管我喜欢Hangfire,但我遇到的情况是我不得不将客户端引导到Quartz.net,因为业务需要每55秒或类似地运行一次。
任何提出反驳论点的人,如果它被配置为每1秒运行一次就会对性能产生严重影响,那么再次对事物采取封闭的看法。当然,间隔1秒的触发器可能不是一个好主意,但是对于不太可能出现1秒钟的情况,我们是否会放弃55秒或45秒?
在任何情况下,性能都是主观的并且取决于主机平台和硬件。在性能方面,实际上不需要API来强制执行意见。只需使轮询间隔和触发重复可配置。这样,用户可以为自己确定最佳结果。
虽然可以选择将作业编排为每55秒运行一次的后台处理,但这并不十分令人满意。在这种情况下,通过Hangfire UI无法看到该过程,因此它对管理员是隐藏的。我觉得这种做法正在绕开Hangfire的主要好处之一。
如果Hangfire是Quartz.net之类的重要竞争者,它至少会匹配他们的基本功能。如果Quartz可以支持间隔低于1分钟的触发器而不是为什么不能Hangfire!
尽管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);
我不知道我的解决方案是多么“万无一失”,但我设法用它来实现我的目标,一切都在生产中“快乐”。
不确定何时获得支持,但在使用Hangfire 1.7.0的ASP.NET Core 2.0中进行了尝试。以下代码每20秒调度一次作业:
RecurringJob.AddOrUpdate<SomeJob>(
x => x.DoWork(),
"*/20 * * * * *");
如果我没有弄错的话,由于Hangfire使用NCrontab而支持6个令牌(而不是标准的5个令牌),这允许使用6个令牌的cron表达式(第二个粒度而不是分钟粒度)。
Hangfire仪表板也很好地显示了运行之间的小时间间隔:
我遇到了同样的问题,这是我的解决方案:
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来避免一些并发冲突。
我有类似的要求,因为我有一个需要每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();
...