具体实现

class DailyTrigger : IDisposable
{
    private TimeSpan TriggerHour { get; }

    private bool Immediate = false;

    public CancellationTokenSource CancellationToken { get; set; }

    private Task RunningTask { get; set; }

    /// <summary>
    /// 定时触发器,在每日的X时X分X秒触发事件
    /// </summary>
    /// <param name="hours">时</param>
    /// <param name="minutes">分</param>
    /// <param name="seconds">秒</param>
    public DailyTrigger(int hours, int minutes, int seconds)
    {
        TriggerHour = new TimeSpan(hours, minutes, seconds);
        CancellationToken = new CancellationTokenSource();
        RunningTask = Task.Run(async () =>
        {
            while (true)
            {
                //计算定时时间和当前时间的时间差
                TimeSpan triggerTime = DateTime.Today + TriggerHour - DateTime.Now;
                //时间差小于零,说明现在的时间大于定时的时间,加一个24小时
                if (triggerTime < TimeSpan.Zero)
                {
                    triggerTime = triggerTime.Add(new TimeSpan(24, 0, 0));
                }
                //开始延时
                await Task.Delay(triggerTime, CancellationToken.Token);
                //触发任务
                OnTimeTriggered?.Invoke();
            }
        }, CancellationToken.Token);
    }

    /// <summary>
    /// 定时触发器,每次间隔X小时X分钟X秒
    /// </summary>
    /// <param name="hours">时</param>
    /// <param name="minutes">分</param>
    /// <param name="seconds">秒</param>
    /// <param name="immediate">定时器启动时,是否立即触发事件</param>
    public DailyTrigger(int hours, int minutes, int seconds, bool immediate)
    {
        TriggerHour = new TimeSpan(hours, minutes, seconds);
        Immediate = immediate;
        CancellationToken = new CancellationTokenSource();
        RunningTask = Task.Run(async () =>
        {
            while (true)
            {
                if (Immediate)
                {
                    OnTimeTriggered?.Invoke();
                    await Task.Delay(TriggerHour, CancellationToken.Token);
                }
                else
                {
                    await Task.Delay(TriggerHour, CancellationToken.Token);
                    OnTimeTriggered?.Invoke();
                }
            }
        }, CancellationToken.Token);
    }

    public event Action OnTimeTriggered;

    public void Dispose()
    {
        CancellationToken?.Cancel();
        CancellationToken?.Dispose();
        CancellationToken = null;
        RunningTask?.Dispose();
        RunningTask = null;
    }

    ~DailyTrigger() => Dispose();
}

使用示例

private async void DoWork()
{
    Console.WriteLine("do something on time");
}
//可以这样设置定时任务,比如每日九点零分零秒执行任务
DailyTrigger dailyTrigger = new DailyTrigger(9, 0, 0);
dailyTrigger.OnTimeTriggered += DoWork;
//可以这样取消定时任务
dailyTrigger.CancellationToken.Cancel();

参考文献

参考链接地址

最后修改:2023 年 08 月 04 日
如果觉得我的文章对你有用,请随意赞赏