2013-08-02 22 views
2

我会做一个计时器,行为是这样的:定时器杀死任务/工作,如果它的运行速度比计时器时间间隔较长

  • 如果处理任务/作业的时间小于定时间隔,启动计时器(timer.interval - 处理时间工作/工作)

  • 如果处理作业的时间/任务比计时器间隔多,开始立刻

代码下面的作品接下来的工作/任务,但我想如T知道为什么必须首先完成ElapsedEventHandler方法作业/任务,然后我们可以设置新的计时器间隔。时间间隔过去后引发System.Timers.Timer事件。使用AutoReset = false选项,我们设置Timer在第一个时间间隔过后仅提升Elapsed事件一次。我们必须手动调用Timer.Start()来重新启动它。

using System; 
using System.Timers; 

namespace TestTimer 
{ 
    class Program 
    { 
     private static Timer t; 
     private static double intervalMiliseconds; 

     static void Main(string[] args) 
     { 
      intervalMiliseconds = 5000; // 5 seconds 

      t   = new Timer(); 
      t.Interval = intervalMiliseconds; 
      t.AutoReset = false; 
      t.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
      t.Start(); 

      log("Timer started at " + DateTime.Now.ToString()); 
      log("Interval is: " + defaultIntervalMiliseconds); 
      Console.ReadKey(); 
     } 

     private static void log(string text) 
     { 
      Console.WriteLine(text + "\n"); 
     } 

     private static void OnTimedEvent(object source, ElapsedEventArgs e) 
     { 
      // if t.Interval is set here thread just kills the job if it 
      // runs longer than interval 
      t.Interval = intervalMiliseconds; 
      log("ElapsedEvent triggered at " + DateTime.Now.ToString()); 

      // job 
      DateTime startTime = DateTime.Now; 
      log("job started"); 
      System.Threading.Thread.Sleep(8000); // 8 sec 
      log("job ended"); 
      TimeSpan jobTime = DateTime.Now.Subtract(startTime); 
      log("job took " + jobTime.TotalSeconds + " seconds"); 

      // if we set t.Interval here it works so first the job 
      // must be done and than we can set timer interval ? why ? 
      //t.Interval = intervalMiliseconds; 

      if (jobTime.TotalMilliseconds < t.Interval) 
      { 
       t.Interval = t.Interval - jobTime.TotalMilliseconds; 
       log("Job ended Earlier starting Event in: " + t.Interval); 
      } 
      else 
      { 
       t.Interval = 100; 
       log("Job overpass interval. Current time: " + 
        DateTime.Now.ToString()); 
      } 

      t.AutoReset = false; 
      t.Start(); 
     } 
    } 
} 

结果呢:

enter image description here

如果我们方法OnTimedEvent并取消t.Interval的工作之后开始评论t.Interval所做的一切工作。这个结果:

enter image description here

为什么我们不能在方法OnTimedEvent开始设置计时器的时间间隔。如果我们这样做,如果任务/作业的运行时间超过了定时器时间间隔,线程就会杀死作业。我真的很感激,如果有人有一些想法?这是否与线程与主线程(哪个定时器运行)的synhronization有关?当我们调用方法OnTimedEvent时,定时器不会再次调用该方法,因为它具有AutoReset = false,它与我们设置定时器属性的位置有什么不同?

+0

虽然我还没有读过你的整个问题,但为什么不在工作_start_上启动计时器。作业完成后,如果计时器已过,则启动另一个作业,否则等待计时器过去。 –

回答

4
t.Interval = intervalMiliseconds; 

这确实是麻烦制造者。这是很直观的行为,一说为MSDN article专门Timer.Interval有关警告在注意:

如果启用和自动复位都设置为false,定时器先前已启用,设置Interval属性的原因Elapsed事件将被提升一次,就好像Enabled属性已被设置为true。要设置间隔而不引发事件,可以暂时将AutoReset属性设置为true。

这是一个相当愚蠢的黑客攻击,但工作。推迟分配值肯定是更好的方法。尽早做它不会给你带来任何麻烦,除非你有AutoReset = false,否则计时器不会打嘀嗒。

System.Threading.Timer是更好的定时器类,它具有许多较少的怪癖。它不会在回调方法中没有任何诊断的情况下吞噬异常。你的代码很敏感,定时器会停止滴答,因为异常会绕过t.Start()调用,你不知道为什么。强力推荐。

+0

它应该被接受。它讲细节。 –

0

!!否,并且从不计时任务/作业如果运行时间超过计时器间隔!

如果任务/作业的处理时间小于定时器间隔的定时器间隔 。 如果作业/任务的处理时间大于定时器间隔,则在定时器间隔/跨度到新线程后启动下一个作业/任务。

所以为了尽量减少空闲时间,你应该保持定时器间隔很小。 在System.Timers.Timer类内部已经执行了Threading。所以不需要执行线程。

+0

您好,欢迎来到Stack Overflow,首先感谢您花时间回答。请花一些时间通过[欢迎导览](https://stackoverflow.com/tour)了解您在这里的方式,阅读[答案]以创建有用的答案并添加到社区中。 – garfbradaz