Home > Mobile >  ASP .Net Core with Quartz.NET 3.4.0
ASP .Net Core with Quartz.NET 3.4.0

Time:09-06

I use Quartz.NET with ASP .Net Core. I want to create scheduler for my app business logic (HelloWorldJob=)), …which can started to execute by event, can paused and resumed by user commands. But something is going wrong, possibly from the beginning(.

So, I created class QuartzHostedService class. In it I configurated job, trigger and scheduler for my business logic. QuartzHostedService public async Task StartAsync(CancellationToken cancellationToken) ” is being executed only once, and started _scheduler with my job - HelloWorldJob. But! The job was never executed! Why?

public class QuartzHostedService : IHostedService
{
    private readonly ISchedulerFactory _schedulerFactory;
    public IScheduler? _scheduler;
    private readonly ILogger<QuartzHostedService> _logger;
    private readonly InitializationModuleConfiguration _initializationModuleConfiguration;
    private  IJobDetail _jobDetail;
    private  bool isEnabled;


    public QuartzHostedService(
        ISchedulerFactory schedulerFactory,
        InitializationModuleConfiguration initializationModuleConfiguration,
        ILogger<QuartzHostedService> logger
        )
    {
        _logger =    logger;
        _schedulerFactory = schedulerFactory;
        _initializationModuleConfiguration = initializationModuleConfiguration;
    }


    public async Task StartAsync(CancellationToken cancellationToken)
    {
        //StdSchedulerFactory factory = new StdSchedulerFactory();

        _scheduler = await _schedulerFactory.GetScheduler();

        await _scheduler.Start();

        // define the job and tie it to our HelloWorldJob class
        _jobDetail = JobBuilder.Create<HelloWorldJob>()
        .WithIdentity("_job", "group")
        .Build();

        ////When you wish to schedule a job, you instantiate a trigger
        ////and 'tune' its properties to provide the scheduling you wish to have.
        ITrigger _trigger = TriggerBuilder.Create()
        .WithIdentity("_trigger", "group")
        .StartNow()
            .WithSimpleSchedule(x => x
            .WithIntervalInSeconds(5)
            .RepeatForever())
        .Build();


        if (_initializationModuleConfiguration.DataLoaderStarted && !isEnabled)
        {
            // Tell quartz to schedule the job using our trigger
            await _scheduler.ScheduleJob(_jobDetail, _trigger);
            isEnabled = true;
        }
        _logger.LogInformation("Execute");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }
}
public class Startup
{
     .......
     .......
        services.AddQuartzHostedService(
            quartz => quartz.WaitForJobsToComplete = true);

        services.AddSingleton<Quartz.ISchedulerFactory, StdSchedulerFactory>();
        services.AddSingleton<HelloWorldJob>();
        services.AddHostedService<QuartzHostedService>();

[DisallowConcurrentExecution]
public class HelloWorldJob: IJob, IHelloWorldJob
{
    private readonly ILogger<HelloWorldJob> _logger;
    public HelloWorldJob(ILogger<HelloWorldJob> logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("Hello world!");
        return Task.CompletedTask;
    }
}

CodePudding user response:

Your code logic looks a bit messy, you can refer to my test code below (Since I don't know the logic of your InitializationModuleConfiguration, I didn't inject this one):

QuartzHostedService:

public class QuartzHostedService : IHostedService
{
    private readonly ISchedulerFactory _schedulerFactory;
    private readonly IJobFactory _jobFactory;

    public QuartzHostedService(
        ISchedulerFactory schedulerFactory,
        IJobFactory jobFactory)
    {
        _schedulerFactory = schedulerFactory;
        _jobFactory = jobFactory;
    }
    public IScheduler Scheduler { get; set; }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
        Scheduler.JobFactory = _jobFactory;

        var job = CreateJob();
        var trigger = CreateTrigger();
        await Scheduler.ScheduleJob(job, trigger, cancellationToken);
        await Scheduler.Start(cancellationToken);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await Scheduler?.Shutdown(cancellationToken);
    }

    private static IJobDetail CreateJob()
    {
            
        return JobBuilder
            .Create<HelloWorldJob>()
            .WithIdentity("_job", "group")
            .Build();
    }

    private static ITrigger CreateTrigger()
    {
        return TriggerBuilder
            .Create()
            .WithIdentity("_trigger", "group")
            .StartNow()
            .WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever())
            .Build();
    }
}

Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddQuartz(q =>
    {
        q.UseMicrosoftDependencyInjectionScopedJobFactory();
    });
    services.AddQuartzHostedService(
        quartz => quartz.WaitForJobsToComplete = true);

    services.AddSingleton<Quartz.ISchedulerFactory, StdSchedulerFactory>();
    services.AddSingleton<HelloWorldJob>();
    services.AddHostedService<QuartzHostedService>();
}

HelloWorldJob:

[DisallowConcurrentExecution]
public class HelloWorldJob : IJob
{
    private readonly ILogger<HelloWorldJob> _logger;
    public HelloWorldJob(ILogger<HelloWorldJob> logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("Hello world!");
        return Task.CompletedTask;
    }
}

Test Result:

enter image description here

Hope this can help you.

CodePudding user response:

Corrected Startup, now it works:

Startup

    services.AddQuartz(q =>
    {
        q.UseDefaultThreadPool(maxConcurrency: 1);
        q.UseMicrosoftDependencyInjectionJobFactory();
    });
    services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
    services.AddSingleton<IHelloWorldJob, HelloWorldJob>();
    services.AddHostedService<QuartzHostedService>();

QuartzHostedService

 public class QuartzHostedService : IHostedService
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private IScheduler _scheduler;
        private readonly ILogger<QuartzHostedService> _logger;
        private readonly InitializationModuleConfiguration _initializationModuleConfiguration;

        public QuartzHostedService(
            ISchedulerFactory schedulerFactory,
            InitializationModuleConfiguration initializationModuleConfiguration,
            ILogger<QuartzHostedService> logger
            )
        {
            _logger =    logger;
            _schedulerFactory = schedulerFactory;
            _initializationModuleConfiguration = initializationModuleConfiguration;
        }


        public async Task StartAsync(CancellationToken cancellationToken)
        {
             _scheduler = await _schedulerFactory.GetScheduler(cancellationToken);

            await _scheduler.Start(cancellationToken);
            // define the job and tie it to our HelloWorldJob class
            var _jobDetail = JobBuilder.Create<IHelloWorldJob>()
            .WithIdentity("_job", "group")
            //.StoreDurably() // we need to store durably if no trigger is associated
            .Build();
            JobKey jobKey = _jobDetail.Key; 

            ////When you wish to schedule a job, you instantiate a trigger
            ////and 'tune' its properties to provide the scheduling you wish to have.
            ITrigger _trigger = TriggerBuilder.Create()
            .WithIdentity("_trigger", "group")
            .StartNow()
                .WithSimpleSchedule(x => x
                .WithIntervalInSeconds(5)
                .RepeatForever())
            .Build();


            if (_initializationModuleConfiguration.DataLoaderStarted)
            {
                // Tell quartz to schedule the job using our trigger
                await _scheduler.ScheduleJob(_jobDetail, _trigger, cancellationToken);
            }
            _logger.LogInformation("Execute");
        }

        public async  Task StopAsync(CancellationToken cancellationToken)
        {
            await _scheduler.Shutdown(cancellationToken);
        }
    }

HelloWorldJob

[DisallowConcurrentExecution]
public class HelloWorldJob : IHelloWorldJob //(IHelloWorldJob implements IJob)
{
    private int count;
    private readonly ILogger<HelloWorldJob> _logger;
    public HelloWorldJob(ILogger<HelloWorldJob> logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        count  ;
        _logger.LogInformation("Hello world!");
        return Task.CompletedTask;
    }
}
  • Related