2011-09-20 177 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, 馬丁