- Quartz.net
- 基础概念
- 基础配置文件
- Scheduler的定义和启用
- 定义相关类
- 相关接口,具体的数据获取和增删改查
- webapi接口使用
Quartz是一个开源的作业调度框架,OpenSymphony的开源项目。Quartz.Net 是Quartz的C#移植版本。
基础概念Scheduler 调度器。
IJob 任务,所有的定时作业都需要继承该类
IJobDetail 给定作业实例的详细属性
JobKey Quartz.IJobDetail的唯一标识
ITrigger 触发器,支持cron和简单基础时间
TriggerKey ITrigger 的唯一标识
例子
public class DayJobs : IJob
{
protected ILogger _logger;//日志,不做过多介绍
protected ILogger logger
{
get
{
if (_logger == null)
_logger = IocContainer.Resolve().Create(this.GetType());
return _logger;
}
}
///
///
///
public DayJobs()
{
_policySdk = new PolicySdkFactory();
}
///
/// 执行,必须实现此方法
///
///
///
public async Task Execute(IJobExecutionContext context)
{
try
{
//test
var test="test";//可打断点直接调试,不做过多处理
}
catch (Exception ex)
{
logger.Error("执行每日任务错误", this.GetType().FullName, ex);
}
await Task.FromResult(true);
}
}
基础配置文件
在此之前需要引用相关nuget,Quartz,Quartz.Jobs,Quartz.Plugins,注意版本,需要对应项目net版本
基础配置可以直接于代码中配置,也可以读取配置文件数据,推荐使用配置文件。
//第一步:在web.configScheduler的定义和启用中加入如下配置 //第二步:定义如下配置 //第三步 具体的作业和定时器定义 quartz_jobs.xml true 每日任务 调度 定时任务 Platform.Infrastructure.Schedulers.Jobs.DayJobs, Platform.Infrastructure true false 日触发器 触发器 每天的23:30发生 每日任务 调度 0 30 23 * * ?
定义
public class SchedulerBase
{
///
/// 调度器基础配置
///
public static Task Scheduler
{
get
{
//已经调整为读取配置文件
NameValueCollection props = new NameValueCollection();
props["quartz.scheduler.instanceId"] = Configs.GetValue("quartz.scheduler.instanceId");
props["quartz.scheduler.instanceName"] = Configs.GetValue("quartz.scheduler.instanceName");
//可视化端口
//props["quartz.scheduler.exporter.port"] = Configs.GetValue("quartz.scheduler.exporter.port");
//props["quartz.scheduler.exporter.bindName"] = Configs.GetValue("quartz.scheduler.exporter.bindName");
//props["quartz.scheduler.exporter.channelType"] = Configs.GetValue("quartz.scheduler.exporter.channelType"); //协议类型
//props["quartz.scheduler.exporter.type"] = Configs.GetValue("quartz.scheduler.exporter.type");
var scheduler = StdSchedulerFactory.GetDefaultScheduler();
return scheduler;
}
}
public static ITrigger AddTrigger(SchedulerReq model)
{
ITrigger dayJobTrigger = TriggerBuilder.Create()
.WithIdentity(model.TriggerName, model.TriggerGroup)
.WithDescription(model.TriggerDescription)
.StartNow()
.WithCronSchedule(model.CronSchedule)
.Build();
return dayJobTrigger;
}
}
public class SchedulerMain
{
private static IScheduler scheduler;
///
/// 定时调度任务
///
public SchedulerMain()
{
}
public void Start()
{
Init().Wait();
}
public async Task Init()
{
scheduler = await SchedulerBase.Scheduler;
// await scheduler.GetJobGroupNames();
//启动调度器
await scheduler.Start();
//执行调度
//await SchedulerBase.AddSchedule(
// new Jobs.JobServer(),
// new Triggers.DayTrigger().SendTrigger(),
// "每日任务", "调度");
}
public void Stop()
{
Shutdown().Wait();
}
public async Task Shutdown()
{
if (scheduler != null)
await scheduler.Shutdown();
}
public static IScheduler GetScheduler()
{
return scheduler;
}
}
启用
Global.asax中的Application_Start中进行Start,就完成了基础的使用
protected void Application_Start()
{
New SchedulerMain().Start();
}
定义相关类
///相关接口,具体的数据获取和增删改查/// 请求参数 /// public class SchedulerReq { ////// 作业名称 /// public string JobName { get; set; } ////// 作业分组 /// public string JobGroup { get; set; } ////// 间隔(Cron) /// public string CronExpression { get; set; } ////// 调度器描述 /// public string TriggerDescription { get; set; } ////// 调度器名称 /// public string TriggerName { get; set; } ////// 调度器所属分组 /// public string TriggerGroup { get; set; } ////// 运行频率 /// public string CronSchedule { get; set; } ////// 程序集 /// public string AssemblyName { get; set; } ////// 命名空间加job所在类名 /// public string ClassName { get; set; } } ////// 结果 /// public class SchedulerResult { ////// 作业名称 /// public string JobName { get; set; } ////// 作业分组 /// public string JobGroup { get; set; } ////// 作业描述 /// public string JobDescription { get; set; } ////// 创建 /// public DateTime? CreateTime { get; set; } ////// 最后执行时间 /// public DateTime? LastRunTime { get; set; } ////// 下次执行时间 /// public DateTime? NextRunTime { get; set; } ////// 间隔(Cron) /// public string CronExpression { get; set; } ////// 调度器描述 /// public string TriggerDescription { get; set; } ////// 调度器名称 /// public string TriggerName { get; set; } ////// 调度器所属分组 /// public string TriggerGroup { get; set; } ////// 任务当前状态 /// public string TriggerState { get; set; } ////// 程序集 /// public string AssemblyName { get; set; } ////// 命名空间加job所在类名 /// public string ClassName { get; set; } }
暂未关联数据库,后期会逐步与数据库关联
public class SchedulerApi
{
private static IScheduler scheduler;
public SchedulerApi()
{
scheduler = SchedulerBase.Scheduler.Result;
}
///
/// 获取任务列表
///
///
public async Task> GetJobs()
{
var list = new List();
var groups = await scheduler.GetJobGroupNames();
foreach (var groupName in groups)
{
foreach (var jobKey in await scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName)))
{
var taskOptions = new SchedulerResult();
var job = scheduler.GetJobDetail(jobKey);
taskOptions.JobDescription = job.Result.Description;
taskOptions.JobName = jobKey.Name;
taskOptions.JobGroup = jobKey.Group;
taskOptions.AssemblyName = job.Result.JobType.Assembly.GetName().Name;
taskOptions.ClassName = job.Result.JobType.FullName;
var triggers = await scheduler.GetTriggersOfJob(jobKey);
foreach (CronTriggerImpl trigger in triggers)
{
//最后执行时间
DateTimeOffset? dateTimePreviousOffset = trigger.GetPreviousFireTimeUtc();
//下次执行时间
DateTimeOffset? dateTimeNextOffset = trigger.GetNextFireTimeUtc();
DateTimeOffset? createTime = trigger.StartTimeUtc;
if (dateTimePreviousOffset != null)
taskOptions.LastRunTime = TimeZoneInfo.ConvertTimeFromUtc(dateTimePreviousOffset.Value.DateTime, TimeZoneInfo.Local);
if (dateTimeNextOffset != null)
taskOptions.NextRunTime = TimeZoneInfo.ConvertTimeFromUtc(dateTimeNextOffset.Value.DateTime, TimeZoneInfo.Local);
if (createTime != null)
taskOptions.CreateTime = TimeZoneInfo.ConvertTimeFromUtc(createTime.Value.DateTime, TimeZoneInfo.Local);
taskOptions.TriggerDescription = trigger.Description;
taskOptions.TriggerName = trigger.Key.Name;
taskOptions.TriggerGroup = trigger.Key.Group;
taskOptions.TriggerState = ((ETriggerState)(int)scheduler.GetTriggerState(trigger.Key).Result).ToString();
taskOptions.CronExpression = trigger.CronExpressionString;
list.Add(taskOptions);
}
}
}
return list;
}
///
/// 添加任务(可自己进行部分修改,例如使用异步,返回不同参数等)
///
///
public void AddJobs(SchedulerReq model)
{
if (!ValidExpression(model.CronSchedule)) Ensure.Error("运行频率,【Cron】表达式设置错误!");
ITrigger trigger = SchedulerBase.AddTrigger(model);
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if (scheduler.CheckExists(jk).Result)
{
Ensure.Error($"任务{model.JobName}已存在!");
}
else
{
Assembly assembly = Assembly.Load(model.AssemblyName);
Type type = assembly.GetType(model.ClassName);
if (type == null) Ensure.Error("Job类错误!");
IJobDetail job = JobBuilder.Create(type).WithIdentity(model.JobName, model.JobGroup).Build();
scheduler.ScheduleJob(job, trigger);
}
}
///
/// 删除任务
///
///
public void DeleteJob(SchedulerReq model)
{
ITrigger trigger = SchedulerBase.AddTrigger(model);
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if ( scheduler.CheckExists(jk).Result)
{
scheduler.DeleteJob(jk);
}
else
{
Ensure.Error($"任务{model.JobName}不存在!");
}
}
///
/// 继续任务
///
///
public void ResumeJob(SchedulerReq model)
{
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if ( scheduler.CheckExists(jk).Result)
{
//任务已经存在则继续任务
scheduler.ResumeJob(jk);
}
}
///
/// 暂停任务
///
///
public void PauseJob(SchedulerReq model)
{
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if ( scheduler.CheckExists(jk).Result)
{
//任务已经存在则暂停任务
scheduler.PauseJob(jk);
}
}
///
/// 更新任务
///
///
public void UpdateJob(SchedulerReq model)
{
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if (scheduler.CheckExists(jk).Result)
{
var triggers = scheduler.GetTriggersOfJob(jk).Result;
ITrigger trigger = triggers?.Where(x => (x as CronTriggerImpl).Name == model.TriggerName).FirstOrDefault();
scheduler.PauseTrigger(trigger.Key);
scheduler.UnscheduleJob(trigger.Key);// 移除触发器
scheduler.DeleteJob(jk);
AddJobs(model);
}
}
///
/// 立即执行
///
///
public void RunJob(SchedulerReq model)
{
JobKey jk = new JobKey(model.JobName, model.JobGroup);
if (scheduler.CheckExists(jk).Result)
{
//任务已经存在则立即执行
scheduler.TriggerJob(jk);
}
}
///
/// 启动任务调度
///
///
public async void StartSchedule()
{
if (!scheduler.IsStarted)
{
//等待任务运行完成
await scheduler.Start();
}
}
///
/// 停止任务调度
///
///
public async void StopSchedule()
{
if (!scheduler.IsShutdown)
{
//等待任务运行完成
await scheduler.Shutdown(false);
}
}
///
/// 校验字符串是否为正确的Cron表达式
///
/// 带校验表达式
///
public bool ValidExpression(string cronExpression)
{
return CronExpression.IsValidExpression(cronExpression);
}
///
/// 验证是否存在任务
///
///
///
///
public bool CheckExists(string name, string group)
{
JobKey jk = new JobKey(name, group);
return scheduler.CheckExists(jk).Result;
}
}
webapi接口使用
直接在控制器中使用即可,只例举获取,其它接口同
public class SchedulerController:BaseController{
private readonly SchedulerApi _schedulerApi;
public SchedulerController()
{
_schedulerApi = new SchedulerApi();
}
///
/// 获取任务列表
///
///
[HttpGet]
[Route("GetJobs")]
[SwaggerResponse(200, "成功返回参数", type: typeof(SchedulerResult))]
public IHttpActionResultGetJobs() {
var list = _schedulerApi.GetJobs().Result;
return Success(list);
}
}
参考链接:
https://www.cnblogs.com/zixuan9527/p/8601151.html
https://github.com/weizhong1988/Weiz.TaskManager/blob/master/Weiz.TaskManager.TaskUtility/Quartz/QuartzHelper.cs



