【问题标题】:Timer every 24 hours at a certain time在特定时间每 24 小时定时器
【发布时间】:2013-09-14 04:41:37
【问题描述】:

我想创建一个计时器,在特定时间每 24 小时调用一次方法。我不想通过 Windows 调度程序执行此操作,而是应该在代码中完成。这是我目前正在使用的代码:

DateTime now = DateTime.Now;
DateTime today = now.Date.AddHours(16);
DateTime next = now <= today ? today : today.addDays(1);

Systems.Threading.TimerCallback callback = new TimerCallback(DisplayMessage);
Systems.Threading.Timer timer = new System.Threading.Timer(callback, null, next - now, TimeSpan.FromHours(24));

我的问题是,如果 next 最终距离当前时间只有几分钟的路程,那么代码将起作用并通过 DisplayMessage() 显示消息。如果时间差大于几分钟,则代码不起作用,没有异常、崩溃或任何情况。我尝试在DisplayMessage() 中放置日志语句、消息框和断点,以确保我能够正确看到何时调用DisplayMessage(),但没有运气。

【问题讨论】:

  • 你有没有看过 Quartz.net。
  • 显而易见的第一个问题:在回调之前,您是否持有对timer 的引用?这是防止它被 GC 所必需的。
  • @McGarnagle 可能就是这样,明天我会尝试并报告。这就解释了为什么它可以在更短的时间内发挥作用。
  • 很好奇,但只是为什么您不想为此使用计划任务?这就是计划任务更多的原因,并且每天使用服务执行一次操作是一种味道。
  • @McGarnagle 就是这样,谢谢

标签: c# timer


【解决方案1】:

这是一个工作示例。

public class Scheduler {
    private readonly List<Task> _Tasks;
    private Timer _Timer;

    public Scheduler() {
        _Tasks = new List<Task>();
    }

    public void ScheduleTask(Task task) {
        _Tasks.Add(task);
    }

    public void CancelTask(Task task) {
        _Tasks.Remove(task);
    }

    //Start the timer.
    public void Start() {
        //Set the interval based on what amount of accurcy you need.
        _Timer = new Timer {
            Interval = 1000
        };

        _Timer.Elapsed += (sender, args) => UpdateTasks();
        _Timer.Enabled = true;
    }

   //Check to see if any task need to be executed.
    private void UpdateTasks() {
        for (int i = 0; i < _Tasks.Count; i++) {
            Task task = _Tasks[i];

            if (task.ExecuteTime >= DateTime.Now) {
                task.Callback();
                _Tasks.Remove(task);
            }

            _Tasks.Remove(task);
        }
    }

    //Stop the timer when you are done.
    public void Stop() {
        _Timer.Dispose();
    }
}

//Use this to schedule a task.
public class Task {
    public DateTime ExecuteTime { get; set; }
    public Action Callback { get; set; }

    public Task(DateTime executeTime, Action callback) {
        ExecuteTime = executeTime;
        Callback = callback;
    }
}

【讨论】:

    【解决方案2】:

    我认为更好的解决方案是让时间每秒触发一次并检查时间和任何你想要的东西,我不认为每秒触发一次是昂贵的过程。 每24小时触发一次不是定时器的正常使用

    【讨论】:

    • 每 24 小时触发一次正是定时器的正常用途之一
    猜你喜欢
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2021-04-03
    相关资源
    最近更新 更多