具体实现
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();