參考:https://www.cnblogs.com/LinWenQiang/p/13460283.html
Quartz 由三個部分組成,分別為Schedule(調度器)、Trigger(觸發器)、JobDetail(任務)
1、首先在項目中添加Quartz nuget 包。
2、創建我們的任務,在項目中添加MyJob,並繼承接口Ijob
[DisallowConcurrentExecution] public class MyJob : IJob { private readonly ILogger<MyJob> _logger; public MyJob(ILogger<MyJob> logger) { _logger = logger; } public Task Execute(IJobExecutionContext context) { _logger.LogInformation("MyJob start"); //在此處編寫任務業務代碼 return Task.CompletedTask; } }
DisallowConcurrentExecution:防止運行多個相同的實例
3、創建調度類JobSchedule
public class JobSchedule { public JobSchedule(Type jobType, string cronExpression) { this.JobType = jobType ?? throw new ArgumentNullException(nameof(jobType)); CronExpression = cronExpression ?? throw new ArgumentNullException(nameof(cronExpression)); } /// <summary> /// Job類型 /// </summary> public Type JobType { get; private set; } /// <summary> /// Cron表達式 /// </summary> public string CronExpression { get; private set; } /// <summary> /// Job狀態 /// </summary> public JobStatus JobStatu { get; set; } = JobStatus.Init; } /// <summary> /// Job運行狀態 /// </summary> public enum JobStatus : byte { [Description("初始化")] Init = 0, [Description("運行中")] Running = 1, [Description("調度中")] Scheduling = 2, [Description("已停止")] Stopped = 3, }
4、添加調度工廠SingletonJobFactory
public class SingletonJobFactory: IJobFactory { private readonly IServiceScope _serviceScope; public SingletonJobFactory(IServiceProvider serviceProvider) { _serviceScope = serviceProvider.CreateScope(); } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { return _serviceScope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob; } public void ReturnJob(IJob job) { (job as IDisposable)?.Dispose(); } }
5、創建QuartzHostedService類,並繼承 IHostedService
public class QuartzHostedService : IHostedService { private readonly IJobFactory _jobFactory; private readonly IEnumerable<JobSchedule> _jobSchedules; public QuartzHostedService(IJobFactory jobFactory, IEnumerable<JobSchedule> jobSchedules) { _jobSchedules = jobSchedules; _jobFactory = jobFactory; } public IScheduler Scheduler { get; set; } public async Task StartAsync(CancellationToken cancellationToken) { Scheduler = await StdSchedulerFactory.GetDefaultScheduler(cancellationToken); Scheduler.JobFactory = _jobFactory; foreach (var jobSchedule in _jobSchedules) { var job = CreateJob(jobSchedule); var trigger = CreateTrigger(jobSchedule); await Scheduler.ScheduleJob(job, trigger, cancellationToken); } await Scheduler.Start(cancellationToken); } public async Task StopAsync(CancellationToken cancellationToken) { await Scheduler?.Shutdown(cancellationToken); } private static IJobDetail CreateJob(JobSchedule schedule) { var jobType = schedule.JobType; return JobBuilder .Create(jobType) .WithIdentity(jobType.FullName) .WithDescription(jobType.Name) .Build(); } private static ITrigger CreateTrigger(JobSchedule schedule) { return TriggerBuilder .Create() .WithIdentity($"{schedule.JobType.FullName}.trigger") .WithCronSchedule(schedule.CronExpression) .WithDescription(schedule.CronExpression) .Build(); } }
6、在Startup進行注冊
public void ConfigureServices(IServiceCollection services) { //添加Quartz服務 services.AddSingleton<IJobFactory, SingletonJobFactory>(); services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>(); //添加我們的Job services.AddScoped<MyJob>();//這里注冊時有個坑,一定要注意 services.AddSingleton( new JobSchedule(jobType: typeof(MyJob), cronExpression: Configuration["TimingTask"]) ); // ... }
定時時間我這里寫到appsettings.json配置文件中了,方便更改:
"TimingTask": "0 45 10 * * ?",
關於Cron表達式,可以看官方文檔:
https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/crontrigger.html#examples