2011-08-12 52 views
1

我有System.Timers.Timer對象的問題。我使用計時器對象來定期執行任務。在計時器構造函數中,我調用執行該工作的方法(DoTimeCheck()),以確保任務在啓動時也運行一次。工作(定期)在BackgroundWorker中完成。System.Timers.Timer延遲掛起應用程序

我叫計時器本:

UpdaterTimer ut = UpdaterTimer.UpdaterTimerInstance; 

我的問題是,我需要用延時3分鐘(運行在應用程序啓動的)任務的第一次運行。後續運行(Elapsed事件)應該立即運行。我想這樣做的,通過調用

System.Threading.Thread.Sleep(TimeToDelayFirstRunInMiliseconds); 

,但失敗了,因爲它也掛起應用程序(主線程)的使其無法使用的UI。如何延遲第一次運行DoTimeCheck()而不掛用戶界面? 定時器的代碼如下。如果問題沒有以清晰的方式呈現,請讓我知道,我會編輯。先謝謝你。

public sealed class UpdaterTimer : Timer 
{ 
    private static readonly UpdaterTimer _timer = new UpdaterTimer(); 
    public static UpdaterTimer UpdaterTimerInstance 
    { 
     get { return _timer; } 
    } 

    static UpdaterTimer() 
    { 
     _timer.AutoReset = true; 
     _timer.Interval = Utils.TimeBetweenChecksInMiliseconds; 
     _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); 
     _timer.Start(); 
     DoTimeCheck(); 

    } 

    static void _timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     DoTimeCheck(); 
    } 

    private static void DoTimeCheck() 
    { 
     //... work here 
    } 
} 
+0

這是整個班級嗎?(只是好奇於從所有靜態方法繼承Timer) –

+0

感謝您的評論 - 除了DoTimeCheck()內部的代碼之外,這是相關的整個類是的。所有的靜態都應該確保只有一個定時器運行 - 一個單身。當然,這可能不是從System.Timers.Timer繼承的最好方式(我是一個newb),但它已經工作到目前爲止。 –

回答

4

這樣做的一種方法是給定時器間隔一個初始值(例如3分鐘)。然後,在您的Elapsed事件處理程序中,您可以將間隔更改爲常規值,然後將使用該值。

_timer.Interval = Utils.InitialCheckInterval; 

static void _timer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    if (_timer.Interval == Utils.InitialCheckInterval) 
    { 
     _timer.Interval = Utils.RegularCheckInterval; 
    } 

    DoTimeCheck(); 
} 
+0

你是否不想將Utils.TimeBetween ...與Utils.RegularInterval交換? – Chris

+0

不要這麼想 - 計時器將被設置爲初始值。然後第一次間隔時間將被改變爲常規時間間隔。 –

+0

我想你是在我和你的評論之間編輯它的,我懷疑你在編輯之後只能看到我的評論。但是,現在看起來不錯。 :) – Chris

0

您的用戶界面需要一個單獨的線程,目前您還在睡覺用戶界面。檢查this post

1

看來,我們在調用主/ GUI線程Sleep(TimeToDelayFirstRunInMiliseconds);(雖然你還沒有證明代碼),所以這是什麼導致你的UI線程掛起。相反,您應該在第一次運行時將計時器設置爲延遲3分鐘,然後一旦運行,您將再次更改計時器以按照您希望的所有後續運行頻率運行。

0

你不應該在這種情況下使用了Thread.Sleep你應該使用的WinForms控制

BackgroundWorker的,從來沒有鎖定主界面。你可以在那裏寫你的邏輯。

例如這裏: http://www.knowdotnet.com/articles/backgroundworker.html

+0

謝謝,但我已經使用BackgroundWorker來完成所有工作。我已經嘗試在BackgroundWorker中添加sleep方法,但是:1 - UI掛起仍然發生,2 - 這意味着延遲將發生在每個timer.Elapsed()事件上,並且我只需要延遲第一次運行。 –

1

您已經在使用定時器細看起來。在啓動另一個計時器之前,只需使用另一個延遲三分鐘即可。

timer = new Timer(); 
timer.AutoReset = false; 
timer.Interval = 3*60*1000; 
timer.Elapsed += startOtherTimerMethod; 
timer.Start(); 

編輯:我要指出,這是大致相同的,除了他的解決辦法是更優雅,因爲它僅使用一個定時器,沒有多餘的方法和需要的事實,即定時器彼得·凱利的回答在運行之間是可變的。如果你喜歡這個答案,你會愛上他的。 ;-)

1

你的用戶界面駐留在同一個線程中,所以當你把線程休眠時,它也會導致你的用戶界面掛起。您需要在另一個線程上運行計時器。

+0

感謝您的評論 - 我只使用BackgroundWorker來完成漫長的工作。除此之外,我遠離多線程,因爲對於我來說這是一塊薄薄的冰,我還沒有很好地理解多線程。 –

+1

你會在這裏需要它。雖然在.NET中有多線程安全的方法,所以不要氣餒。看看這個鏈接:http://msdn.microsoft.com/en-us/library/ms951089.aspx –