有没有办法每隔几秒设置一次篝火重复工作? 我不寻求一个解决方案,即火灾和忘记任务会产生另一个火灾和忘记任务,如果没有,建议的替代方案是什么?
答案 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仪表板还很好地显示了两次运行之间的较小时间间隔:
答案 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 * * * * *");