代码之家  ›  专栏  ›  技术社区  ›  Makach

将服务与计时器同步

  •  2
  • Makach  · 技术社区  · 15 年前

    我正在尝试用c语言编写一个服务,该服务应该在给定日期的给定间隔(超时)上运行。如果日期是在将来,服务应该等待启动,直到到达日期时间。

    例子:

    • 如果我将超时设置为从21:00:00开始的1小时,我希望程序每小时运行一次

    我已经用下面的代码实现了这一点,但是它有一些问题!

    1. 当我安装服务(使用installutil)时,服务被标记为 因为我的线程。睡眠()'. 此服务似乎处于挂起状态,并且在启动之前一直在“安装”。

    我想到的备选方案:

    • 包括使用'超时。间隔“第一次,然后在随后的通话中重置,但感觉不对劲。

    缩写示例:

    public Service()
    {
        _timeout = new TimeSpan(0,1,0,0);
        _timer = new System.Timers.Timer();
        _timer.Interval = _timeout.TotalMilliseconds;
        _timer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);            
    }
    
    private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
    {            
        lock (_obj)  
        { 
            // Stuff that could take a lot of time
        }
    }
    
    public static void Main()
    {
        Run(new Service());
    }
    
    protected override void OnStart(string[] args)
    {
        long current = DateTime.Now.Ticks;
        long start = new DateTime(2010,9,15,21,0,0).Ticks;
        long timeout = _timeout.Ticks;
        long sleep;
    
        if (current > start)
            sleep = timeout - ((current % timeout)) + (start % timeout);
        else
            sleep = start - current;
    
        Thread.Sleep(new TimeSpan(sleep));
    
        _timer.AutoReset = true;
        _timer.Enabled = true;
        _timer.Start();
    }
    
    3 回复  |  直到 15 年前
        1
  •  1
  •   BrokenGlass    15 年前

    必须将计时器逻辑移动到从OnStart例程派生的单独线程。这样您的逻辑就不能干扰SCM,服务将正常启动。

    编辑:只是为了详细说明-对于这个任务,我不认为计时器工作得很好,因为你没有考虑时钟校正,这可能会导致偏差(甚至是不正确的,如果用户手动更改时钟时间)。这就是为什么我更喜欢用小时间间隔来比较时钟时间。

    这个 Run

        public void run()
        {
            while (processing)
            {
                //initiate action on every full hour
                if (DateTime.Now.Second == 0 && DateTime.Now.Minute == 0)
                {
                    //Do something here
                    DoSomething();
                    //Make sure we sleep long enough that datetime.now.second > 0
                    Thread.Sleep(1000);
                }
                Thread.Sleep(100);
            }
        }
    
        2
  •  2
  •   Jim Mischel    15 年前

    这是更容易与一个 System.Threading.Timer

    所以,如果你想在开始前等待2天,然后每小时做一次,你可以这样写:

    Timer MyTimer = new Timer(TimerCallback, null, TimeSpan.FromHours(48), TimeSpan.FromHours(1));
    

    也就是说,如果这是一个每小时只需要运行一次的程序,那么听起来您真正想要的是一个可执行文件,然后使用Windows任务调度器进行调度。

        3
  •  2
  •   Dave Clemmer manu    13 年前

    你可以使用 System.Threading.Timer . 它支持 dueTime 和一个 period

    推荐文章