目录
介绍
Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,轮询处理问题,邮件通知,定时处理数据等。Quartz.NET根据Corn表达式时间间隔(秒时分天年月日)来调度作业。Quartz由3个组成部分,调度器Schedule,任务JobDetail,触发器Trigger。官网地址Home | Quartz.NET
NuGet依赖
Quartz(Quart库),Quartz.Extensions.Hosting(后台运行扩展),Quartz.Extensions.DependencyInjection(Quartz依赖注入相关)
值得注意的是有了Quartz.Extensions.DependencyInjection这个包,我们不需要在Program中额外增加类型注册的工作,可以直接通过构造函数注入对应的Quartz接口,使用对应实例
个人业务Job
这里完全是自己的业务逻辑代码,不用太在意Quartz
//不允许并发执行
[DisallowConcurrentExecution]
public class TestJob : IJob
{
ITestService testService;
ILogger<ContractJob> _logger;
public TestJob(ITestService testService, ILogger<TestJob> logger)
{
this.testService= testService;
this._logger = logger;
}
public Task Execute(IJobExecutionContext context)
{
try
{
testService.GetTestName();
Console.WriteLine($"job execute:{DateTime.Now}");
//throw new Exception("Test Error");
}
catch (Exception ex)
{
_logger.LogError(ex, $"TestJob异常:{ex.Message}");
//quartzFactory.Stop().GetAwaiter();
throw ex;
}
return Task.CompletedTask;
}
Program Quartz配置
builder.Host.ConfigureServices((hostContext, services) =>
{
services.AddQuartz(q =>
{
//自动注入Quartz相关类
q.UseMicrosoftDependencyInjectionJobFactory();
q.UseDefaultThreadPool(tp =>
{
tp.MaxConcurrency = 10;
});
//向Job中传参
var jobDataDic = new Dictionary<string, string>
{
{ "JobName", "TestJob" }
};
//job名称和组名称
var jobKey = new JobKey("TestJob", "group");
var jobDataMap = new JobDataMap(jobDataDic);
//添加job
q.AddJob<TestJob>(opts => opts.WithIdentity(jobKey).SetJobData(jobDataMap));
//添加触发器
q.AddTrigger(opts => opts
.ForJob(jobKey)
.WithIdentity("TestJob-trigger")
.WithCronSchedule(config["Corn"]));
//配置几个自定义监听器
q.AddSchedulerListener<SchedulerListener>();
q.AddJobListener<JobListener>();
q.AddTriggerListener<TriggerListener>();
});
services.AddQuartzHostedService(options =>
{
// when shutting down we want jobs to complete gracefully
options.WaitForJobsToComplete = true;
});
});
此时job配置已经完成
上面需要注意的是TestJob是自己的业务逻辑,Quartz的类型注册,不会注入,需要我们额外注册一次
containerBuilder.RegisterType<ContractJob>().AsSelf().InstancePerDependency(); //这里是Autofac的注册方式,也可以用.net6自己的注册方式,殊途同归
代码列出所有任务及状态
IScheduler scheduler;
ISchedulerFactory schedulerFactory;
ILogger<TestController> logger;
public TestController( ILogger<TestController> logger, ISchedulerFactory schedulerFactory)
{
this.schedulerFactory = schedulerFactory;
this.logger = logger;
}
[HttpGet("GetAllJobs")]
public async Task<List<QuarzJobsDto>> GetAllJobs()
{
var jobList = new List<QuarzJobsDto>();
var matcher = GroupMatcher<JobKey>.AnyGroup();
try
{
scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();
var jobKeys = scheduler.GetJobKeys(matcher).GetAwaiter().GetResult();
foreach (var jobKey in jobKeys)
{
var triggers = scheduler.GetTriggersOfJob(jobKey).GetAwaiter().GetResult();
foreach (var trigger in triggers)
{
TriggerState triggerState = scheduler.GetTriggerState(trigger.Key).GetAwaiter().GetResult();
QuarzJobsDto dto = new QuarzJobsDto()
{
JobDetailName=jobKey.Name,
GroupName=jobKey.Group,
JobCronExpression=$"触发器:{trigger.Key}",
Status=triggerState.ToString()
};
jobList.Add(dto);
}
}
}
catch (Exception ex)
{
logger.LogError(ex, $"GetAllJobs:{ex.Message}");
}
return jobList;
}
ISchedulerFactory 已经被自动注入过,不需要自己手动注册,直接使用就好