原來工作中有用到定時任務Quartz,不過是在MVC項目中,現在net core項目中也要用到,就開始改版。中間發現在網上的教程只有執行定時計劃的過程,卻很少有人寫註冊的過程,覺得有點略坑。所以寫此文章一是自己做個記錄,二是希望能幫助到其他人。後面還把此功能做出了多任務定時執行,網上關於net co ...
原來工作中有用到定時任務Quartz,不過是在MVC項目中,現在net core項目中也要用到,就開始改版。中間發現在網上的教程只有執行定時計劃的過程,卻很少有人寫註冊的過程,覺得有點略坑。所以寫此文章一是自己做個記錄,二是希望能幫助到其他人。後面還把此功能做出了多任務定時執行,網上關於net core的教程更是少了,花費了不少時間實現了出來。
Quartz版本:3.0.7
1.NuGet中下載安裝Quartz
2.新建Quartz幫助類
(1)新建QuartzJob類,代碼如下:
public class QuartzJob : IJob { public async Task Execute(IJobExecutionContext context) { var jobKey = context.JobDetail.Key;//獲取job信息 var triggerKey = context.Trigger.Key;//獲取trigger信息 LogHelper.Info($"{DateTime.Now} QuartzJob:==>>自動執行.{jobKey.Name}|{triggerKey.Name}"); await Task.CompletedTask; } }
ps: 上面代碼中的jobKey和triggerKey可獲取到自己定義的job和trigger的信息,這樣做多任務時可區分要執行的是哪個任務. 另LogHelper.Info是自己封裝好的日子記錄類,可替換為自己的日誌類
(2)新建QuartzFactory類,代碼如下:
public class QuartzFactory : IJobFactory { private readonly IServiceProvider _serviceProvider; public QuartzFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { var jobDetail = bundle.JobDetail; var job = (IJob)_serviceProvider.GetService(jobDetail.JobType); return job; } public void ReturnJob(IJob job) { } }
(3)新建QuartzService類,代碼如下:
#region 單任務 public static void StartJob<TJob>() where TJob : IJob { var scheduler = new StdSchedulerFactory().GetScheduler().Result; var job = JobBuilder.Create<TJob>() .WithIdentity("job") .Build(); var trigger1 = TriggerBuilder.Create() .WithIdentity("job.trigger") .StartNow() .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(5)).RepeatForever()) .ForJob(job) .Build(); scheduler.AddJob(job, true); scheduler.ScheduleJob(job, trigger1); scheduler.Start(); } #endregion #region 多任務 public static void StartJobs<TJob>() where TJob : IJob { var scheduler = new StdSchedulerFactory().GetScheduler().Result; var job = JobBuilder.Create<TJob>() .WithIdentity("jobs") .Build(); var trigger1 = TriggerBuilder.Create() .WithIdentity("job.trigger1") .StartNow() .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(5)).RepeatForever()) .ForJob(job) .Build(); var trigger2 = TriggerBuilder.Create() .WithIdentity("job.trigger2") .StartNow() .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(11)).RepeatForever()) .ForJob(job) .Build(); var dictionary = new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>> { {job, new HashSet<ITrigger> {trigger1, trigger2}} }; scheduler.ScheduleJobs(dictionary, true); scheduler.Start(); } #endregion #region 配置 public static void AddQuartz(this IServiceCollection services, params Type[] jobs) { services.AddSingleton<IJobFactory, QuartzFactory>(); services.Add(jobs.Select(jobType => new ServiceDescriptor(jobType, jobType, ServiceLifetime.Singleton))); services.AddSingleton(provider => { var schedulerFactory = new StdSchedulerFactory(); var scheduler = schedulerFactory.GetScheduler().Result; scheduler.JobFactory = provider.GetService<IJobFactory>(); scheduler.Start(); return scheduler; }); } #endregion
3.在Startup.cs中註冊代碼
public void ConfigureServices(IServiceCollection services) { services.AddQuartz(typeof(QuartzJob));
//........ } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { QuartzService.StartJobs<QuartzJob>(); //........ }
ps: 因AddQuartz方法定義的是Type[]類型,所以可傳多個執行類,如:services.AddQuartz(typeof(QuartzJob1), typeof(QuartzJob2)); 不過這樣做StartJob()方法就得另處理下,這裡就略過
OK,大功告成,這個東西折騰了兩天終於塵埃落定了,執行結果如下: