2011-09-20 167 views
1

使用C#,.NET Framework 4.0。 我有3个TimeSpan对象设置为20分钟,30分钟,45分钟。我希望只有在确切的时间间隔内才能执行定时器,无论定时器何时启动。 我需要计时烧成这个样子的(每小时):等待定时器,运行每个时间间隔?

timerA 1:00 
timerB 1:00 
timerA 1:20 
timerB 1:30 
timerA 1:40 
timerC 1:45 
timerA 2:00 
timerB 2:00 
timerA 2:20 
timerB 2:30 
timerA 2:40 
timerC 2:45 

我想到了一个可等待计时器将是正确的选择,但由于缺乏简单的例子摆在那里,我想不会。获得此功能的最佳方式是什么(如果可能,我希望避免时钟漂移,但我现在对任何事情都绝望)?我没有和Waitable结婚。我也明白,timerC只会每小时运行一次,这很好,因为它只能在每小时的第45分钟运行。

注 - 我没有准备好使用Quartz.NET。

谢谢。

+0

你能解释一下你想做什么吗? –

+0

@Snowy,你在用什么编程语言? 。净?此外,在你的例子中,计时器C每小时执行一次,而不是每45分钟执行一次......那是你真正想要的吗? – Kiril

+1

只使用一个计时器,以便它们永远不会分开。将其设置为下一个到期间隔,然后梳理需要完成的工作。总是从时钟计算时间间隔,不要增加一个增量,因为它总是会漂移很晚。 –

回答

1

我认为这将做的工作适合你:

static void Main(string[] args) 
{ 
    StartTimer(TimeSpan.FromMinutes(20.0), "TimerA", true); 
    StartTimer(TimeSpan.FromMinutes(30.0), "TimerB", true); 
    StartTimer(TimeSpan.FromMinutes(45.0), "TimerC", true); 

    Console.WriteLine("Press any key to exit..."); 
    Console.ReadLine(); 
} 

启动定时器功能启动定时器,并返回它(如果你需要参考)。这里的关键是你给它定时器名称,并告诉它是否要将定时器对准整个小时。如果你不想对准整个小时,那么定时器将立即以指定的频率启动。

public static Timer StartTimer(TimeSpan frequency, string timerName, bool alignToHour) 
{ 
    if (alignToHour) 
    { 
     return new Timer(OnTimerTick, timerName, ComputeDelay(frequency), frequency); 
    } 
    else 
    { 
     return new Timer(OnTimerTick, timerName, TimeSpan.Zero, frequency); 
    } 
} 

当计时器滴答时将被触发的函数。

public static void OnTimerTick(object state) 
{ 
    Console.WriteLine((string)state + " " + DateTime.Now.ToString("H:mm")); 
} 

此方法计算如果定时器必须在整小时对齐时所需的延迟。它只适用于频率小于1小时或超过1分钟的情况。

public static TimeSpan ComputeDelay(TimeSpan frequency) 
{ 
    if (frequency > TimeSpan.FromHours(1.0) || 
     frequency < TimeSpan.FromMinutes(1.0)) 
    { 
     throw new ArgumentException(
      "The frequency cannot be more than one hour or less than one minute!"); 
    } 

    return frequency - TimeSpan.FromMinutes(DateTime.Now.Minute % frequency.Minutes); 
} 

注:在您的示例运行在1小时频率45分钟计时器,但你上20次分钟和30分钟的频率(分别)运行20倍分钟和30分钟的定时器。我的代码在1小时的频率上无法使用45分钟的定时器,但它在各自的频率上使用20,30和45分钟的定时器。我不确定你的例子是否错误,但如果没有错,那么我认为你应该能够弄清楚如何从这里处理这种差异。

1

我能得到的最接近的是在目标时间上爬行,使用可等待的(sleep(),具有超时的事件,一些线程计时器或经典的主线程窗口计时器),设置为从现在到目标时间之间的毫秒数,从实时时钟计算出来。如果剩余的ms大于某个限制(例如500),则重新确定剩余的ms并再次等待。当剩余的ms低于限制时,开始循环实时时钟,直到达到或超过目标,然后调用TimeSpan对象的timeout()方法。

您可以将TimeSpan对象放入超时时间有序队列,以便您只需要一个等待队列。这可能会更精确,如果您遇到TimeSpan事件经常“同时”发生的情况,因为目标时间接近时只有一个线程循环。

RGDS, 马丁