2010-06-16 38 views
7

我想爲WinForm創建一個後臺工作器,每當午夜過後觸發代碼。背景工作人員檢查什麼時候是午夜?

我有一個想法如何做到這一點,但我非常確定這不是最好的方式來做到這一點。

while(1==1) 
{ 
//if Datetime.Now == midnight, execute code 
//sleep(1second) 
} 
+0

快速提示...如果你想要創建一個「無盡的」循環(當然可以有一個「break」),你可以使用while(true){}。無論如何,1 == 1的計算結果都是「真」的。 – 2010-06-16 13:46:09

+0

這是公認的標準嗎?我從來沒有確定使用1 == 1 – sooprise 2010-06-16 14:11:46

回答

21

使用System.Timers.Timer並在應用程序啓動時,只需計算DateTime.NowDateTime.Today.AddDays(0)之間的差異即可。然後設置該金額的時間間隔。

我真的做到了,就像這家新近:

public static class DayChangedNotifier 
{ 
    private static Timer timer; 

    static DayChangedNotifier() 
    { 
     timer = new Timer(GetSleepTime()); 
     timer.Elapsed += (o, e) => 
      { 
       OnDayChanged(DateTime.Now.DayOfWeek); 
       timer.Interval = this.GetSleepTime(); 
      }; 
     timer.Start(); 

     SystemEvents.TimeChanged += new EventHandler(SystemEvents_TimeChanged); 
    } 

    private static void SystemEvents_TimeChanged(object sender, EventArgs e) 
    { 
     timer.Interval = GetSleepTime(); 
    } 

    private static double GetSleepTime() 
    { 
     var midnightTonight = DateTime.Today.AddDays(1); 
     var differenceInMilliseconds = (midnightTonight - DateTime.Now).TotalMilliseconds; 
     return differenceInMilliseconds; 
    } 

    private static void OnDayChanged(DayOfWeek day) 
    { 
     var handler = DayChanged; 
     if (handler != null) 
     { 
      handler(null, new DayChangedEventArgs(day)); 
     } 
    } 

    public static event EventHandler<DayChangedEventArgs> DayChanged; 
} 

AND:

public class DayChangedEventArgs : EventArgs 
{ 
    public DayChangedEventArgs(DayOfWeek day) 
    { 
     this.DayOfWeek = day; 
    } 

    public DayOfWeek DayOfWeek { get; private set; } 
} 

用途:DayChangedNotified.DayChanged += ....

+0

的好處所以我甚至不需要一個後臺工作者? – sooprise 2010-06-16 13:45:01

+0

@Soo:沒有。計時器不會阻止(停止其他代碼 - http://en.wikipedia.org/wiki/Blocking_%28computing%29)。一旦間隔到了,它會調用'Tick'事件。此時可以根據需要停止定時器,計算下一個時間間隔並重新啓動它。 – 2010-06-16 13:47:44

+0

不,System.Timers在另一個線程上觸發,所以你需要小心的是在你的定時器的事件處理程序中調用Invoke。 – BFree 2010-06-16 13:50:51

7

相反,您可以使用計時器並將計時器滴答時間間隔設置爲Now()和午夜之間的時間。

0

您可以使用Quartz來安排。在這種情況下,也許就像大炮殺死蚊子一樣,但這是我所知道的唯一的調度工作框架,並且非常出色。

0

不要使用輪詢。相反,請設置一個計時器任務,將其設置爲在午夜觸發,並添加要處理的事件。

TimeSpan timeBetween = DateTime.Today.AddDays(1) - DateTime.Now; 

System.Timers.Timer t = new System.Timers.Timer(); 
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); 
t.Interval = 1000 * timeBetween.Seconds; 
t.Start(); 
+0

因此在t_Elapsed被觸發之後,timeBetween是否被重新計算? – sooprise 2010-06-16 14:07:06

+0

您將重新計算t_Elapsed方法中的時間間隔。 – cortijon 2010-06-16 18:40:23

0

我不知道爲什麼投票解決方案被投票了,當微軟多年前通過添加一個Windows服務來解決這類問題來處理時間。只需創建一個計劃任務來運行該exe。沒有額外的開銷。

0

我對你爲什麼需要一個WinForm有點困惑,它會在午夜運行嗎?如果你只需要一些排序過程就可以運行,使用Windows調度程序在午夜運行它。 (在XP上,但我相信Win服務器應該是類似的)控制面板 - >計劃任務 - >添加計劃任務 - >填寫嚮導。爲您節省很多編碼。