如何让 Timer 在特定时间点触发?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让 Timer 在特定时间点触发?相关的知识,希望对你有一定的参考价值。
咨询区
Behrooz Karjoo
我的应用程序需要做一个 事件触发
的功能,它需要每天定时执行,比如说当天的 16点,我现在的做法是使用一个 timer 按秒轮询判断当前是否为 16:00
, 虽然可以玩得转,但我想能不能实现那种 16:00
自动触发回调函数的模式,而不是现在无时无刻的轮询。
回答区
noontz
其实很简单,计算触发时间与当前时间的差值,然后将 差值
作为精确的延迟时间,带入到 Task.Delay
中即可,外面再套个 while(true)
,下面是我封装的代码。
/// <summary>
/// Utility class for triggering an event every 24 hours at a specified time of day
/// </summary>
public class DailyTrigger : IDisposable
/// <summary>
/// Time of day (from 00:00:00) to trigger
/// </summary>
TimeSpan TriggerHour get;
/// <summary>
/// Task cancellation token source to cancel delayed task on disposal
/// </summary>
CancellationTokenSource CancellationToken get; set;
/// <summary>
/// Reference to the running task
/// </summary>
Task RunningTask get; set;
/// <summary>
/// Initiator
/// </summary>
/// <param name="hour">The hour of the day to trigger</param>
/// <param name="minute">The minute to trigger</param>
/// <param name="second">The second to trigger</param>
public DailyTrigger(int hour, int minute = 0, int second = 0)
TriggerHour = new TimeSpan(hour, minute, second);
CancellationToken = new CancellationTokenSource();
RunningTask = Task.Run(async () =>
while (true)
var triggerTime = DateTime.Today + TriggerHour - DateTime.Now;
if (triggerTime < TimeSpan.Zero)
triggerTime = triggerTime.Add(new TimeSpan(24, 0, 0));
await Task.Delay(triggerTime, CancellationToken.Token);
OnTimeTriggered?.Invoke();
, CancellationToken.Token);
/// <inheritdoc/>
public void Dispose()
CancellationToken?.Cancel();
CancellationToken?.Dispose();
CancellationToken = null;
RunningTask?.Dispose();
RunningTask = null;
/// <summary>
/// Triggers once every 24 hours on the specified time
/// </summary>
public event Action OnTimeTriggered;
/// <summary>
/// Finalized to ensure Dispose is called when out of scope
/// </summary>
~DailyTrigger() => Dispose();
然后像下面这样使用。
void Main()
var trigger = new DailyTrigger(16); // every day at 4:00pm
trigger.OnTimeTriggered += () =>
// Whatever
;
Console.ReadKey();
点评区
思路是个好思路,不过在正式的项目开发中,建议还是用 Quartz.NET
或者 HangFire
这种专业的调度框架,毕竟它支持强大的 Cron 表达式。
RecurringJob.AddOrUpdate(() => MyMethod(), "* 16 * * *");
以上是关于如何让 Timer 在特定时间点触发?的主要内容,如果未能解决你的问题,请参考以下文章