0

In my case I am enqueueing messages to a queue in Run() method. After the job is fired for the first time, another instance starts each time interval passes, and they continue to work together. How can I prevent a new one from starting if there is an active instance? It is a .netcore 3.1 project. I tried with Quartz 3.2.0 and 3.2.4. Here is job scheduling, JobFactory and Job, sequentially.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System.Collections.Specialized;
using System.Threading;
using System.Threading.Tasks;
using WinSchedulerLib;

namespace MessageSender.WinService
{
    public class MessageSenderService : IHostedService
    {
        public static IScheduler scheduler;
        public static IJobFactory jobFactory;

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            var props = new NameValueCollection { { "quartz.serializer.type", "binary" } };
            var factory = new StdSchedulerFactory(props);
            var scheduler = await factory.GetScheduler();

            var services = new ServiceCollection().AddScoped<IJob, MessageSenderJob>();
            var serviceProvider = services.BuildServiceProvider();

            jobFactory = new JobFactory(serviceProvider);
            scheduler.JobFactory = jobFactory;

            await scheduler.Start();
            await scheduler.ScheduleJob(
                JobBuilder
                    .Create<IJob>()
                    .WithIdentity("SenderJob", "SenderGroup")
                    .Build(),
                TriggerBuilder
                    .Create()
                    .WithIdentity("SenderJob", "SenderGroup")
                    .StartNow()
                    .WithCronSchedule("0 */10 * ? * *")
                    .Build());
            await Task.Delay(1000);
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }
    }
}
using Quartz;
using Quartz.Spi;
using System;

namespace WinSchedulerLib
{
    public class JobFactory : IJobFactory
    {
        protected readonly IServiceProvider _serviceProvider;

        public JobFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
        }

        public void ReturnJob(IJob job)
        {
            var obj = job as IDisposable;
            obj?.Dispose();
        }
    }
}
using Quartz;
using System.Threading.Tasks;

namespace MessageSender.WinService
{
    [DisallowConcurrentExecution]
    public class MessageSenderJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
                var sender = new DefaultServiceBusSender();
                await sender.Run();
        }
    }
}
  • https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#job-state-and-concurrency – madreflection Feb 17 '21 at 17:00
  • Does this answer your question? [In Quartz.NET is there a way to set a property that will only allow one instance of a Job to run?](https://stackoverflow.com/questions/5984220/in-quartz-net-is-there-a-way-to-set-a-property-that-will-only-allow-one-instance) – madreflection Feb 17 '21 at 17:02
  • Unfortunately no. I am already using `[DisallowConcurrentExecution]` attribute and have tried misfire instructions. They did not provide a solution. – Ahmet Said Feb 17 '21 at 19:26
  • You should also check out the [built-in container registration support](https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/microsoft-di-integration.html#using). – Marko Lahma Feb 22 '21 at 06:30
  • Thank you @MarkoLahma, I will check it out. – Ahmet Said Mar 09 '21 at 06:27

1 Answers1

0

Changing the lines

var services = new ServiceCollection().AddScoped<IJob, MessageSenderJob>();
await scheduler.ScheduleJob(
    JobBuilder
        .Create<IJob>()
        .WithIdentity("SenderJob", "SenderGroup")
        .Build(),
    TriggerBuilder
        .Create()
        .WithIdentity("SenderJob", "SenderGroup")
        .StartNow()
        .WithCronSchedule("0 */10 * ? * *")
        .Build());

to

var services = new ServiceCollection().AddScoped<MessageSenderJob>();
await scheduler.ScheduleJob(
    JobBuilder
        .Create<MessageSenderJob>()
        .WithIdentity("SenderJob", "SenderGroup")
        .Build(),
    TriggerBuilder
        .Create()
        .WithIdentity("SenderJob", "SenderGroup")
        .StartNow()
        .WithCronSchedule("0 */10 * ? * *")
        .Build());

solved it.