在 Quartz.NET 中,有没有一种方法可以设置一个属性,只允许一个作业实例运行?
我有一项服务每 X 分钟运行一次。如果由于某种不可预见的原因该作业花费的时间超过 X 分钟,我想确保触发器不会启动该作业的第二个实例。
示例场景
- 我有作业 X,拾取文件并由 Quartz 每 1 分钟触发一次。
- 作业 X 通常可以在 1 分钟内处理 100 个文件,超过 100 个文件将花费超过 1 分钟的时间。
- 自上次运行以来,恰好有 150 个文件存在,因此作业 X 启动并开始处理。当达到 1 分钟时,已处理 100 个文件,剩余 50 个文件,作业 X 继续运行。
- 然而,作业 X 的第二个实例已启动,因为触发器每 1 分钟触发一次。
- 我现在有 2 个 Job X 实例拾取相同的 50 个文件。
有没有办法连接 Quartz.NET 以仅允许一个作业实例?我可以接受第二个触发器等待第一个触发器完成,或者我也可以选择跳过第二个触发器,因为它会在一分钟内再次触发。
我查看了 Quartz API 的 Java 版本,发现了一个属性 'DisallowConcurrentExecution',但在.NET版本中没有找到类似的。
我的 Quartz.NET 实现代码
public IScheduler Scheduler { get; set; }
public IJobListener AutofacJobListener { get; set; }
public void Start()
{
var trigger = TriggerUtils.MakeMinutelyTrigger(1);
trigger.Name = @"Document Import Trigger";
Scheduler.ScheduleJob(new JobDetail("Document Import", null, typeof(DocumentImportJob)), trigger);
Scheduler.AddGlobalJobListener(AutofacJobListener);
Scheduler.Start();
}
I have a service that will run every X minutes. If that job takes longer than X minutes for some unforeseen reason I want to make sure that the trigger doesn't kick off a second instance of this job.
Sample Scenario
- I have Job X, picks up files and is triggered by Quartz every 1 minute.
- Job X can typically process 100 files in 1 minute, anything over 100 files will take longer than 1 minute.
- Since the last run time, 150 files happen to be out there so Job X kicks off and begins processing. When 1 minute is reached 100 files were processed, 50 files remain, and Job X continues to run.
- However a second instance of Job X is kicked off because the trigger fires every 1 minute.
- I now have 2 instances of Job X picking up the same 50 files.
Is there a way to wire up Quartz.NET to only allow 1 instance of a Job? I'm OK with the second trigger waiting for the first to complete or I'm also OK with an option for it to skip the second trigger since it will be triggered again in a minute.
I took a look at the Java version of Quartz API and found a property 'DisallowConcurrentExecution' but didn't find one similar in the .NET version.
My Code for the Quartz.NET Implementation
public IScheduler Scheduler { get; set; }
public IJobListener AutofacJobListener { get; set; }
public void Start()
{
var trigger = TriggerUtils.MakeMinutelyTrigger(1);
trigger.Name = @"Document Import Trigger";
Scheduler.ScheduleJob(new JobDetail("Document Import", null, typeof(DocumentImportJob)), trigger);
Scheduler.AddGlobalJobListener(AutofacJobListener);
Scheduler.Start();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用 DisallowConcurrentExecution 属性。
按如下方式声明您的类:
Misfires
查看这些页面底部的“触发失火说明”信息:
第 5 课:SimpleTrigger
第 6 课:CronTrigger
旧 Quartz.NET API 答案:
http://quartznet.sourceforge.net/apidoc/topic142.html:
因此,请按如下方式声明您的“作业”类:
为了避免作业完成后立即重新触发延迟任务(当作业花费超过 1 分钟并导致触发器“失火”时),请在创建触发器时执行以下操作(根据使用的触发器类型进行调整):
https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-triggers.html
Use the DisallowConcurrentExecution attribute.
Declare your class as follows:
Misfires
Check out the "trigger misfire instructions" information at the bottom of these pages:
Lesson 5: SimpleTrigger
Lesson 6: CronTrigger
Old Quartz.NET API answer:
http://quartznet.sourceforge.net/apidoc/topic142.html:
So, declare your 'Job' class as follows:
To avoid delayed tasks re-firing immediately after job completes (when the job takes more than 1 minute and causes a trigger 'misfire'), do the following when creating your trigger(s) (adjust depending on the trigger type used):
https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-triggers.html
作为此答案的更新,在较新版本的 Quartz.Net 中,现在通过应用于作业实现的属性“DisallowConcurrentExecution”来完成:
对于失火指令,以下是如何做到这一点:
As an update to this answer, in newer versions of Quartz.Net this is now done via an attribute "DisallowConcurrentExecution" you apply to your job implementation:
And for the misfire instruction, here is how to do that:
好吧,一种简单的方法是将标志值存储在某个变量中,并在进入作业方法时检查该变量。
这样你就可以让工作第二次“开始”,它会立即退出而不做任何实际的工作。
这是一个例子:
Well, one simple way to do it would be to just store a flag value in a variable somewhere, and check the variable upon entrance to the job method.
That way you would just let the job "start" a second time, it would just exit immediately without doing any real work.
Here's an example:
公共 bool Validar(IJobExecutionContext 上下文)
{
public bool Validar(IJobExecutionContext context)
{