In my scheduler, implemented with quartz.net v3, i'm trying to test the behaviour of the cancellation token:
....
IScheduler scheduler = await factory.GetScheduler();
....
var tokenSource = new CancellationTokenSource();
CancellationToken ct = tokenSource.Token;
// Start scheduler
await scheduler.Start(ct);
// some sleep
await Task.Delay(TimeSpan.FromSeconds(60));
// communicate cancellation
tokenSource.Cancel();
I have a test Job that runs infinitely and in the Execute
method checks the cancellation token:
public async Task Execute(IJobExecutionContext context)
{
while (true)
{
if (context.CancellationToken.IsCancellationRequested)
{
context.CancellationToken.ThrowIfCancellationRequested();
}
}
}
I would expect that when tokenSource.Cancel()
is fired the job will enter in the if
and throws the Exception. But it doesn't work.
According to the documentation, you should use Interrupt
method to cancel Quartz
jobs.
NameValueCollection props = new NameValueCollection
{
{ "quartz.serializer.type", "binary" }
};
StdSchedulerFactory factory = new StdSchedulerFactory(props);
var scheduler = await factory.GetScheduler();
await scheduler.Start();
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob", "group1")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithRepeatCount(1)
.WithIntervalInSeconds(40))
.Build();
await scheduler.ScheduleJob(job, trigger);
//Configure the cancellation of the schedule job with jobkey
await Task.Delay(TimeSpan.FromSeconds(1));
await scheduler.Interrupt(job.Key);
Scheduled job class;
public class HelloJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
while (true)
{
if (context.CancellationToken.IsCancellationRequested)
{
context.CancellationToken.ThrowIfCancellationRequested();
// After interrupt the job, the cancellation request activated
}
}
}
}
Apply scheduler.Interrupt
after the job executed and the quartz will terminate the job.
EDIT
According to source code (Line 2151), the Interrupt
method applys cancellation tokens of the job execution contexts. So, it could be better to use facility of the library.
Here is a Unit Test from Github Repo: https://github.com/quartznet/quartznet/blob/master/src/Quartz.Tests.Unit/InterrubtableJobTest.cs
I tried to implement the cancellation the same way, but it didn't work for me either.
@Stormcloak I have to check the cancellation request because I want to do some aborting operations for the job, e.g. write status data to a database.
EDIT:
So, after multiple tests and implementations. I've got it running.
Some Pseudo code here:
this.scheduler = await StdSchedulerFactory.GetDefaultScheduler();
this.tokenSource = new CancellationTokenSource();
this.token = tokenSource.Token;
// Start scheduler.
await this.scheduler.Start(token);
// add some jobs here
// ...
// cancel running jobs.
IReadOnlyCollection<IJobExecutionContext> jobs = await this.scheduler.GetCurrentlyExecutingJobs();
foreach (IJobExecutionContext context in jobs)
{
result = await this.scheduler.Interrupt(context.JobDetail.Key, this.token);
}
await this.scheduler.Shutdown(true);
So now you can use the CancellationToken in your Execute method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With