2013-08-02 55 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