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:
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;
}
}