原文參考: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()