2009-02-08 46 views
3

考慮下面的代碼定時器在Delphi

Timer1 .Enabled := False; 
Timer1.Interval : = 300; 
For I := 1 to NumberOfTimesNeed do 
Begin 

    Timer1 .Enabled := False; // 
    Timer1 .Enabled := True;  // reset the timer to 0.30 seconds 

    TakesToLong  := False; 
    DoSomethingThatTakesTime; // Application.ProcessMessages is called in the procedure 

    If TakesToLong = True then 
     TakeAction; 
End; 

procedure Timer1Timer(Sender: TObject); 
begin 
    TakesToLong:= True; 
end; 

問:

當我禁用,然後啓用定時器1與

Timer1.Enabled := False; 
Timer1.Enabled := True; 

這是否復位定時器?

即它會在超時之前總是等待0.30秒。

+9

呃,你爲什麼不試試?沒有0.3秒的空閒時間? ;) – 2009-02-08 14:27:37

回答

16

是的,它會的。如果之前啓用了定時器,將Enabled設置爲False將調用Windows API函數KillTimer()。如果定時器之前未啓用,將Enabled設置爲True將調用Windows API函數SetTimer()。

這是一個標準的成語,因爲德爾福的時代已經工作1

不過,我想實現你的代碼以不同的方式:

Start := GetSystemTicks; 
DoSomethingThatTakesTime; 
Duration := GetSystemTicks - Start; 

if Duration > 300 then 
    TakeAction; 

這將不定時工作,而不需要在long-taking方法中調用ProcessMessages()。 GetSystemTicks()是我在庫中的一個函數,它在Windows中調用timeGetTime(),並且對Kylix執行不同的操作(不記得我是如何在很久以前清除代碼的)。

+1

很好的回答,甚至更好的建議! – 2009-02-08 10:00:44

+0

@mghie我改變了使用GetSystemTicks的代碼,它很好用,謝謝:) – 2009-02-09 05:58:49

+0

或者,考慮使用[等待計時器](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687012的.aspx)。 [創建計時器](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682492.aspx)一次,然後在每次循環迭代中,您可以[(重新啓動計時器]](https ://msdn.microsoft.com/en-us/library/windows/desktop/ms686289.aspx),完成你的工作(不用擔心消息處理),最後使用`WaitForSingleObject()`以0ms超時來查看是否定時器已過。 – 2017-01-19 04:10:11

1

我建議閱讀主題。長時間的操作(我不是說300毫秒很長,但它聽起來像是明顯可能會比這更長)往往會凍結GUI並導致應用程序波濤洶涌。現在,您可以在其中放入application.processmessages以保持GUI的運行,但它可以輕鬆地拋棄您的預期程序編碼風格。

我從認爲Application.ProcessMessages過道的一側是應該禁止,除非你是一個VB程序員試圖用Delphi模仿的DoEvents,你還沒有得到出的VB心態。

生成一個線程並在該線程中完成您的工作。如果想在完成後更新GUI端,請將「同步」調用爲「安全」。通過線程來回傳播進行中的狀態帶來了一個全新的對話,這個對話雖然使用了定時器控制,但卻是一個很大的飛躍。

1

還有一件事要注意的是定時器是系統上最低優先級的通知。所以如果電腦很忙,這可能包括這裏的應用程序在做它的工作,計時器可能不會觸發很長一段時間。因此,即使計時器設置爲300毫秒,TakesToLong變量設置爲true也可能需要幾秒鐘。