全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:6887
推到 Plurk!
推到 Facebook!

請問如何寫排程程式?

尚未結案
小蟲蟲
一般會員


發表:38
回覆:55
積分:23
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-10-09 10:03:53 IP:203.73.xxx.xxx 未訂閱
我想寫一隻程式,使用者可以設定在每天的幾點的時候執行某程式(使用者可以設定多個排程)。我不想用"AT"指令或是附屬應用程式中的"排程事件"(因為那些都有可能被"好奇"的使用者刪除或修改),曾經想用一個Timer一直在計算時間,但覺得有點不可靠(每秒觸發一次事件,會不會造成系統的負擔?) 請問:有沒有比較可靠的排程寫法? 謝謝大家
Miles
尊榮會員


發表:27
回覆:662
積分:622
註冊:2002-07-12

發送簡訊給我
#2 引用回覆 回覆 發表時間:2002-10-09 10:38:51 IP:210.58.xxx.xxx 未訂閱
Hello : 你可以先寫一個計算時間的函式(毫秒), 再直接填入Timer中, 這樣就不會有每秒觸動的情形, 譬如:

function CountTime(ProcessTime: TDateTime): Integer;
var NowTime : TDateTime;
begin
   NowTime := Time;
   Result := Trunc((ProcessTime - NowTime) * 24 * 60 * 60 * 1000);
end;    procedure TForm1.Button1Click(Sender: TObject);
var : MyProcessTime;
begin
   MyProcessTime := StrToTime('18:00:00');
   Timer1.Enabled := False;
   Timer1.Interval := CountTime(MyProcessTime);
   Timer1.Enabled := True;
end;
------


我不是高手, 高手是正在銀幕前微笑的人.
小蟲蟲
一般會員


發表:38
回覆:55
積分:23
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2002-10-09 15:11:48 IP:203.73.xxx.xxx 未訂閱
引言: Hello : 你可以先寫一個計算時間的函式(毫秒), 再直接填入Timer中, 這樣就不會有每秒觸動的情形
如果有多個排程,如一個在早上八點執行,一個在晚上7點執行,沒有規則性,那應該如何作?要動態產生多個Timer嗎? 謝謝!
Dalman
一般會員


發表:27
回覆:22
積分:24
註冊:2002-08-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2002-10-09 21:44:38 IP:211.74.xxx.xxx 未訂閱
我提出我的思考佈局給你參考看看: 一、使用 Thread 來分派處理不同時間點的排程工作執行。 二、使用 client-side 資料庫(如 Access)來儲存各個時間點工作資訊。 三、利用 Timer 每隔 n 分鐘去輪詢資料表 m 筆記錄,看是否有指定排程工作,若是有的話便立即建立排程 Thread 執行,並在資料表該筆記錄上更新狀態資料。 四、若有需要,可以在排程 Thread 執行完成後,將日誌(log)資訊寫入資料庫內,做為以後歷史查閱或統計資料來源。 五、連 Timer 都可以使用 Thread 來實做,而且幾乎感覺不到 CPU loading 吃重(我因專案實務而得知的且有應用過,Timer為每五秒一次輪詢 MSSQL 資料五筆,CPU loading 低於 3%,CPU Speed=1.4 GHz)。 六、呵呵,你可能會問這個 ThreadTimer 哪裡得?自己有參考網路上他人發表程式碼實做一個 _TThreadTimer 單元應用於專案上。 希望上述文字可以給你一個明確方向。
小蟲蟲
一般會員


發表:38
回覆:55
積分:23
註冊:2002-03-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2002-10-11 09:47:56 IP:203.73.xxx.xxx 未訂閱
謝謝!我先試試您說_TThreadTimer。
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2002-10-20 14:47:48 IP:203.204.xxx.xxx 未訂閱
要按使用者設定時間作事,一定得有 Timer ,而 Timer 準不準並不重要,重要的是在 Timer 內作什麼? 依你的需求,在 Timer 內應先讀取目前的時間,判斷是否有某個設定的排程時間已到且未執行,如果有,則去讀取該排程相關的資料,依設定資料叫用其他程式,同時設定此排程已執行,如果需要,則重新設定此排程的下一次執行時間,並重新此新的排程尚未執行,如此可以作到每小時執行一次或每十分鐘執行一次。 而排程設定的時間資料可以直接放在記憶體中,不要每次 Timer 來才去讀設定檔,這樣才能減少磁碟 IO 才不會造成 CPU Loading,時間在 BCB/Delphi 中使用 double 來存才占 8 bytes 不會有太占記憶體。這樣即使每秒比對一次對 CPU 的 Loading 應該都在 1% 以下,即使是有 100 筆排程設定值以 C500 的 CPU 比對 100 筆的浮點數大小再加一個 bool 是否已執行的旗標應該是沒什麼問題。 是否開多個 ThreadTimer 來處理每一個排程?以上述的作法應該是可以不用了,只需要主程式的一個 Timer 就夠了,而這個 Timer 如果是 ThreadTimer 當然會更好,這樣就可以讓使用者設定此排程軟體的優先權。    沒空更新的網頁...
C及指標教學,計算機概論,資訊管理導論... http://coolsite.to/dllee 介紹Shells,LiteStep,GeoShell.... http://coolsite.to/ushells
------
http://www.ViewMove.com
kkccgg
初階會員


發表:50
回覆:54
積分:30
註冊:2002-07-28

發送簡訊給我
#7 引用回覆 回覆 發表時間:2002-10-21 22:01:44 IP:203.204.xxx.xxx 未訂閱
1.對於Timer其實只要開一個比較不會有問題偶通常是利用一個一秒觸發一次Timer然後將執型的程序加上時間這樣可以結省很多資源. 2.之前偶有用Timer去做通訊程式撰寫他是持續且不能關閉但最後發現Timer竟會停掉真的很可怕不曉得問題出在哪當時用的OS是NT 128M Ram,P233M HZ這個問題不曉得是否有人遇過    謝謝
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#8 引用回覆 回覆 發表時間:2002-10-21 22:13:04 IP:61.221.xxx.xxx 未訂閱
參考看看 PostgreSQL VS Delphi http://pgsql.vip.idv.tw/viewtopic.php?t=398
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
Dalman
一般會員


發表:27
回覆:22
積分:24
註冊:2002-08-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2002-10-24 00:50:17 IP:61.59.xxx.xxx 未訂閱
小弟我已經將 _TThreadTimer VCL 單元分享出來了,你可以去看看使用一下。
miga
初階會員


發表:61
回覆:92
積分:30
註冊:2002-08-27

發送簡訊給我
#10 引用回覆 回覆 發表時間:2002-10-29 21:10:43 IP:211.74.xxx.xxx 未訂閱
我也需要寫一個排程的程式… 可是毫無頭緒…不知從何下手… 有人可以推廌一下相關的書或網路上的文章嗎… 我有找過幾本delphi的書… 好像都不會寫到… 謝謝
小蟲蟲
一般會員


發表:38
回覆:55
積分:23
註冊:2002-03-13

發送簡訊給我
#11 引用回覆 回覆 發表時間:2002-10-30 10:22:14 IP:203.73.xxx.xxx 未訂閱
謝謝大家幫忙,目前我是使用2個ThreadTimer來做排程的動作。這個Threadtimer是我在網路上找到的,與前一篇大大所Post的類似,但看起來前一篇所寫的比較完整。如果大家有需要,可以參考參考。 至於為什麼我用2個ThreadTimer呢?我做了一個測試: //當按下Button時,產生一個ThreadTimer,並設定Interval為1秒。 procedure TForm1.Button1Click(Sender: TObject); begin FTimer := TThreadedTimer.Create(Self); FTimer.Interval := 1000; FTimer.Enabled := True; FTimer.OnTimer := TimerProcedure; FCount := -1; end; //在TimerProcedure內做的事是將系統時間列在Memo1中, //並且使之超過Timer的Interval procedure TForm1.TimerProcedure(Sender: TObject); var ADate, ATime: TDateTime; iCount: integer; strDT: string; iIndex: integer; begin Inc(FCount); ADate := Date Time; Memo1.Lines.Add('Begin--' DateTimeToStr(ADate)); for iCount := 0 to 1000 do begin ADate := Now; strDT := DateTimeToStr(ADate); ADate := StrToDateTime(strDT); Memo1.Lines.Add('During--' DateTimeToStr(ADate)); end; Memo1.Lines.Add('End--' DateTimeToStr(ADate)); end; 結果: Begin--2002/10/30 上午 10:13:59 During--2002/10/30 上午 10:13:59 During--2002/10/30 上午 10:13:59 ... During--2002/10/30 上午 10:14:00 During--2002/10/30 上午 10:14:00 ... During--2002/10/30 上午 10:14:01 During--2002/10/30 上午 10:14:01 ... During--2002/10/30 上午 10:14:02 During--2002/10/30 上午 10:14:02 ... During--2002/10/30 上午 10:14:03 During--2002/10/30 上午 10:14:03 ... During--2002/10/30 上午 10:14:04 During--2002/10/30 上午 10:14:04 ... During--2002/10/30 上午 10:14:05 During--2002/10/30 上午 10:14:05 ... End--2002/10/30 上午 10:14:05 Begin--2002/10/30 上午 10:14:06 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 如果在OnTimer所做的事超過Timer的Interval,則可能會跳過幾個Interval。我的排程程式是以秒為單位,並且不予許跳秒的事情發生。 所以,我的做法為: 一、一個Timer負責計算時間,如果時間到的時候,將要做的事情寫入一ThreadList中。 二、第二個Timer負責每隔五秒去檢查ThreadList內有沒有東西,如果有,則取出,並從List中刪除,執行之。 三、原本是想說當第一個Timer時間到時,立即產生一個Thread,由這個Thread去做要做的事,這是我的理想做法,有可能在同一時間會有好幾個Thread在執行。不幸地,我的程式會有同步的問題,且目前我沒這個需求。 再次謝謝大家的幫忙,也提出我的做法,讓大家參考參考
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2002-11-02 13:51:15 IP:203.204.xxx.xxx 未訂閱
引言: 如果在OnTimer所做的事超過Timer的Interval,則可能會跳過幾個Interval。我的排程程式是以秒為單位,並且不予許跳秒的事情發生。 所以,我的做法為: 一、一個Timer負責計算時間,如果時間到的時候,將要做的事情寫入一ThreadList中。 二、第二個Timer負責每隔五秒去檢查ThreadList內有沒有東西,如果有,則取出,並從List中刪除,執行之。 三、原本是想說當第一個Timer時間到時,立即產生一個Thread,由這個Thread去做要做的事,這是我的理想做法,有可能在同一時間會有好幾個Thread在執行。不幸地,我的程式會有同步的問題,且目前我沒這個需求。 再次謝謝大家的幫忙,也提出我的做法,讓大家參考參考
您的第一個 Timer 計時以秒為單位,試問是您自己計時嗎? 還是每次會讀取系統時間呢? 如果您自己計時,而不讀取系統時間,那這樣的排程一定會不準的! 特別是在支援「暫停」、「休眠」的電腦,你的 Timer 會因系統暫停或休眠而停止計時喔。 沒空更新的網頁...
C及指標教學,計算機概論,資訊管理導論... http://coolsite.to/dllee 介紹Shells,LiteStep,GeoShell.... http://coolsite.to/ushells
------
http://www.ViewMove.com
小蟲蟲
一般會員


發表:38
回覆:55
積分:23
註冊:2002-03-13

發送簡訊給我
#13 引用回覆 回覆 發表時間:2002-11-02 16:25:27 IP:61.230.xxx.xxx 未訂閱
引言: 您的第一個 Timer 計時以秒為單位,試問是您自己計時嗎? 還是每次會讀取系統時間呢? 如果您自己計時,而不讀取系統時間,那這樣的排程一定會不準的!
請教,什麼是自己計時與每次讀取系統時間? 我目前的做法是在ThreadTimer內 if WaitForSingleObject(gEventObj, Interval) = WAIT_TIMEOUT then begin Synchronize(fireOnTimer); end; 等待Interval。 當Interval時間到,而觸發TimerProcedure時,讀取系統時間,看看是否需要執行排程。 請問這種做法安全嗎?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#14 引用回覆 回覆 發表時間:2002-11-03 10:16:21 IP:203.204.xxx.xxx 未訂閱
引言:
引言: 您的第一個 Timer 計時以秒為單位,試問是您自己計時嗎? 還是每次會讀取系統時間呢? 如果您自己計時,而不讀取系統時間,那這樣的排程一定會不準的!
請教,什麼是自己計時與每次讀取系統時間? 我目前的做法是在ThreadTimer內 if WaitForSingleObject(gEventObj, Interval) = WAIT_TIMEOUT then begin Synchronize(fireOnTimer); end; 等待Interval。 當Interval時間到,而觸發TimerProcedure時,讀取系統時間,看看是否需要執行排程。 請問這種做法安全嗎?
我所要說的只是,必需要「讀取系統時間」才不會有問題。 而所謂的自己計時是:假設 Timer 可以每秒執行一次,自己寫程式計秒。 但不論是什麼 Timer 都有可能會不準,所以一定不能自己計時,而要在 OnTimer 時用 Now() 或其他的函式讀取系統時間。 沒空更新的網頁...
C及指標教學,計算機概論,資訊管理導論... http://coolsite.to/dllee 介紹Shells,LiteStep,GeoShell.... http://coolsite.to/ushells
------
http://www.ViewMove.com
brucetsao
一般會員


發表:1
回覆:33
積分:11
註冊:2002-09-11

發送簡訊給我
#15 引用回覆 回覆 發表時間:2003-04-22 15:44:16 IP:61.219.xxx.xxx 未訂閱
1.用timer物件,當然會不準,當ontimer時,先now()教時,後在查schedule table ,在送進去job queue去做,在return system opertaion
系統時間:2024-04-29 22:25:05
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!