原文参考:https://www.cnblogs.com/osscoder/p/10036062.html
实现方式基于上文,根据自己的实际情况做了配置上的小修改,供同行参考,如有不对的地方欢迎指正
首先是 BaseJobTrigger,在原构造函数中添加了timeType字段用来读取配置文件,适应性更强

/// <summary> /// 触发器基类 /// </summary> public abstract class BaseJobTrigger : IHostedService, IDisposable { //定义Timer线程 private Timer _timer; //定义任务延迟执行的时间 private readonly TimeSpan _dueTime; //定义任务的间隔触发事件 private readonly TimeSpan _periodTime; //定义任务的具体执行者 private readonly IJobExecutor _jobExcutor; #region 构造函数1 /// <summary> /// 构造函数 /// </summary> /// <param name="dueTime">延期执行时间(默认立即执行)</param> /// <param name="timer">延迟执行的时间值</param> /// <param name="timeType"> 1=FromDays 2=FromHours 3=FromMinutes 4=FromSeconds 5=FromMilliseconds</param> /// <param name="jobExcutor">任务执行者</param> protected BaseJobTrigger(TimeSpan dueTime,int timeType,int timer,IJobExecutor jobExcutor) { _dueTime = dueTime; _jobExcutor = jobExcutor; if (timeType == 1) _periodTime = TimeSpan.FromDays(timer); else if (timeType == 2) _periodTime = TimeSpan.FromHours(timer); else if (timeType == 3) _periodTime = TimeSpan.FromMinutes(timer); else if(timeType == 4) _periodTime = TimeSpan.FromSeconds(timer); else _periodTime = TimeSpan.FromMilliseconds(timer); } #endregion #region 构造函数2 /// <summary> /// 构造函数 /// </summary> /// <param name="dueTime">延期执行时间(默认立即执行)</param> /// <param name="periodTime">定义任务的间隔触发事件</param> /// <param name="jobExcutor">任务执行者</param> protected BaseJobTrigger(TimeSpan dueTime, TimeSpan periodTime, IJobExecutor jobExcutor) { _dueTime = dueTime; _periodTime = periodTime; _jobExcutor = jobExcutor; } #endregion #region 计时器相关方法 /// <summary> /// 启动TimerTrigger /// </summary> private void StartTimerTrigger() { if (_timer == null) _timer = new Timer(ExcuteJob, _jobExcutor, _dueTime, _periodTime); else _timer.Change(_dueTime, _periodTime); } /// <summary> /// 停止TimerTrigger /// </summary> private void StopTimerTrigger() { _timer?.Change(Timeout.Infinite, Timeout.Infinite); } /// <summary> /// 具体的Job /// </summary> /// <param name="obj"></param> private void ExcuteJob(object obj) { try { var excutor = obj as IJobExecutor; excutor?.StartJob(); } catch (Exception e) { LogUtil.ErrorLog($"执行任务({nameof(GetType)})时出错,信息:{e}"); } } #endregion #region 系统级任务执行启动 /// <summary> /// 系统级任务执行启动 /// </summary> /// <returns></returns> public virtual Task StartAsync(CancellationToken cancellationToken) { try { StartTimerTrigger(); } catch (Exception e) { LogUtil.ErrorLog($"启动定时任务({nameof(GetType)})时出错,信息:{e}"); } return Task.CompletedTask; } #endregion #region 系统级任务执行关闭 /// <summary> /// 系统级任务执行关闭 /// </summary> /// <returns></returns> public virtual Task StopAsync(CancellationToken cancellationToken) { try { _jobExcutor.StopJob(); StopTimerTrigger(); } catch (Exception e) { LogUtil.ErrorLog($"停止定时任务({nameof(GetType)})时出错,信息:{e}"); } return Task.CompletedTask; } #endregion #region 资源释放 public void Dispose() { _timer?.Dispose(); } #endregion }
然后是TimeJobTirgger,继承自基类,负责初始化参数

public class TimeJobTirgger:BaseJobTrigger { public static int timeType; public static int timer; public static int delay_start_timer; public static string sqlConn; /// <summary> /// TimeJobTirgger 触发器继承自BaseJobTrigger,在构造函数时传入 任务执行的延迟时间,任务执行的间隔以及具体的任务类 /// </summary> public TimeJobTirgger() : base(TimeSpan.FromMinutes(delay_start_timer), timeType, timer, new TimeJobExcutor(sqlConn)) { } }
下来是TimeJobExcutor,具体负责执行

/// <summary> /// 继承自IJobExecutor 是具体执行任务的工作类 /// </summary> public class TimeJobExcutor : IJobExecutor { //从容器中获取对象 private readonly BeWXUserApp _app = AutofacExt.GetFromFac<BeWXUserApp>(); private readonly BeWXMsgApp _msgApp = AutofacExt.GetFromFac<BeWXMsgApp>(); private readonly AppBasicDataApp _basicApp = AutofacExt.GetFromFac<AppBasicDataApp>(); private static string _sqlConn; public TimeJobExcutor(string sqlConn) { _sqlConn = sqlConn; } public void StartJob() { LogUtil.InfoLog("执行任务!"); //InitDataAndUpdateRemark(); //初始化本地表及完善remark和list信息 SendMonthMsg(); //释放资源 StopJob(); } public void StopJob() { LogUtil.InfoLog("系统终止任务"); } }
然后是在StartUp类的ConfigureServices方法中注册服务

//注册定时任务计划(从配置文件获取参数) TimeJobTirgger.timeType = int.Parse(Configuration.GetSection("Setting").GetValue<string>("timer_planning_type").ToString()); TimeJobTirgger.timer = int.Parse(Configuration.GetSection("Setting").GetValue<string>("timer_planning_timer").ToString()); TimeJobTirgger.delay_start_timer = int.Parse(Configuration.GetSection("Setting").GetValue<string>("delay_start_timer").ToString()); TimeJobTirgger.sqlConn = Configuration.GetConnectionString("Database").ToString(); services.AddHostedService<TimeJobTirgger>();
最后是配置文件
"Setting": { "timer_planning_type": "2", "timer_planning_timer": "20", "delay_start_timer": "20" },
为了更好的读取配置文件, 我创建了同名的Setting类,类中的属性和配置文件中保持一致,那么就可以通过以下方式来读取了
Configuration.GetSection("Setting").GetValue<string>("timer_planning_timer").ToString()