1

I have a routine which is suppose to run at 9am everyday....

protected override void OnStart(string[] args)
{
   log.Info("Info - Service Start");
   string timeToRunStr = "09:00";
   var timeStrArray = timeToRunStr.Split(';');
   foreach (var strTime in timeStrArray)
   {
        timeToRun.Add(TimeSpan.Parse(strTime));
   }
    ResetTimer();
}

void ResetTimer()
{
   log.Info("Info - Reset Timer");
   try
   {
       TimeSpan currentTime = DateTime.Now.TimeOfDay;
       TimeSpan nextRunTime = timeToRun[0];
       foreach (TimeSpan runTime in timeToRun)
       {
           if (currentTime < runTime)
           {
               nextRunTime = runTime;
               // log.Info("Info - in loop");
               _timer = new Timer((nextRunTime - currentTime).TotalSeconds * 1000);
               break;
           }
           else {
             TimeSpan test = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 16, 51, 0).AddDays(1).Subtract(DateTime.Now);
             nextRunTime = test;
              _timer = new Timer((nextRunTime).TotalSeconds * 1000);
            }
        }               
        log.Info("Info - Timer : " + (nextRunTime - currentTime).TotalSeconds * 1000);
        log.Info("Info - nextRuntime : " + nextRunTime);
        log.Info("Info - currentTime : " + currentTime);
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        _timer.Start();
    }
    catch (Exception ex)
    {
        log.Error("This is my timer error - ", ex);
    }
}

it runs at 9am then next run time it says 1.09:00:00 does this mean 9am tomorrow?

4

2 回答 2

7

1.09:00:00 表示时间跨度为 1 天 9 小时

于 2012-06-20T08:02:58.170 回答
4

MSDN 文档:

TimeSpan 值可以表示为 [-]d.hh:mm:ss.ff,其中可选的减号表示负时间间隔,d 分量是天,hh 是按 24 小时制测量的小时数,mm是分钟,ss 是秒,ff 是秒的分数。也就是说,时间间隔由正数或负数的天数组成,没有一天中的时间,或者包含一天中的时间的天数,或者只有一天中的时间。

在您的实例中,TimeSpan 为 1 天 9 小时 0 分钟和 0 秒。

回答您的实际问题:

它在上午 9 点运行,然后下一个运行时间显示 1.09:00:00 这是否意味着明天上午 9 点?

这取决于 - 如果您将时间跨度添加到当前时间(即当前批次完成时),它将为您提供第二天下午 6 点左右的时间。您需要使用 DateTime.Now.Date (给定日期的午夜)并将时间跨度添加到第二天早上 9 点。

但是,那里有很多调度 组件,您可能会发现它们更易于使用(或至少阅读其代码)——这取决于您对准确性和恢复的要求。

在您的原始方法中,您可能会发现更简单:

protected override void OnStart(string[] args)
{
   log.Info("Info - Service Start");
   DateTime startTime = DateTime.Date.AddHours(9); //9AM Today
   timeToRun.Add(startTime); 
   CreateTimer();
}

void CreateTimer()
{
   log.Info("Info - Reset Timer");
   try
   {
      if(_timer == null){
         _timer = new Timer(3600 * 1000); //once an hour
         _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
         _timer.Start();
      }
    }
    catch (Exception ex)
    {
        log.Error("This is my timer error - ", ex);
    }
}

然后,在您的 timer_elapsed 事件中,您只需执行以下操作(请原谅事件签名,它来自内存):

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
   if(DateTime.Now > timeToRun[0])
   {
      //Code to run the job
      //Then we reset the timer - can do this here or at the end of the job code
      timeToRun[0] = DateTime.Date.AddDays(1).AddHours(9); //9AM tomorrow.
    }

 }

你的重置计时器太复杂了——你不需要所有的代码。您只需创建一个计时器,让它每小时检查一次,如果现在时间大于作业运行时间,则运行作业,并将下一个运行时间移至明天上午 9 点。对于像这样的简单计时器,这就是您需要做的一切。

这种方法的问题包括它不是细粒度的。这项工作可能不会在上午 9 点开始,所以如果这重要,最好调查我提到的链接调度库之一。

于 2012-06-20T08:18:08.093 回答