有此幾乎遺留代碼,涉及一個簡單的TThread,用作定時器,基於WaitForSingleObject的()和事件句柄,像這樣WaitForSingleObject的帶超時的超時
TTimerThread = class(TThread)
private
FInterval: cardinal;
FEvent: THandle;
FSomeClass: TSomeClass;
protected
procedure Execute; override;
end;
....
procedure TTimerThread.Execute;
var res: cardinal;
begin
repeat
log('Start WaitForSingleObject() with %d', [FInterval]);
res := WaitForSIngleObject(FEvent, FInterval);
log('End WaitForSingleObject() with result %d', [res]);
if res = WAIT_TIMEOUT then
if not Terminated then
Synchronize(FSomeClass.SomeMethod);
until Terminated;
end;
的代碼之後返回長有些應用程序特定的失敗檢查(何時不會觸發)和日誌記錄方面有點縮減。
的日誌調用會在類似於日誌文件中顯示:
2016/11/12 17:49:08:056 $1130 llDebug Start WaitForSingleObject() with 20
2016/11/12 17:49:09:015 $1130 llDebug End WaitForSingleObject() with result 258
登錄功能與格式打印的值現在,$ 1130當前線程,llDebug是記錄等級。這兩個調用之間沒有任何記錄(日誌文件是「功能」/「模塊」)
在這種情況下,等待時間高達959毫秒!
的下降事件件在主線程(就像線程計時器本身),像這樣創建:
FEvent := CreateEvent(nil, false, false, nil);
所以線程本身不會產生窗戶,也沒有使用COM或類似的東西。如果SomeMethod會使用這種方法,它將在一個Synchronized調用中,以便在主線程中執行。然而,對於這個特定的測試,SomeMethod只是在TImage上繪製。
該代碼計算FInterval爲20 ms。該線程大約每30/31 ms觸發一次,最有可能是由於Windows計時器分辨率。
我們有1個客戶運行Windows 10,其中WaitForSingleObject(),每隔幾分鐘(相隔好幾分鐘)只會在400+毫秒後返回。
SomeMethod在1 ms內執行,因爲它沒有做太多處理。
我們不需要高分辨率的計時器,因爲當前的代碼在其他地方工作的很好,每30毫秒一次就足夠了,即使是10-15毫秒的「錯誤」也是如此。
定時器控制一堆操作,這就是爲什麼它以大約20ms的間隔執行,但是對於這個問題,我們已經消除了所有其他操作(顯式地),只剩下1個操作正在運行,這就是我們如何調試這個請參閱WaitForSingleObject()每隔幾分鐘400或400 ms後不返回。
在WaitForSingleObject()之前有一個日誌調用,並且在一個之後(也記錄了間隔),所以100%確定WaitForSingleObject()在400ms以上返回,即使時間間隔是20ms。 如預期的那樣,日誌記錄顯示WaitForSingleObject()的返回值爲WAIT_TIMEOUT。
問題是:在WaitForSingleObject()中可能導致此行爲的原因是什麼? 我的意思是我可以理解幾個ms額外由於CPU繁忙,太多的線程(不是在這個應用程序的情況下),但在峯值負載小於30%的系統上差不多半秒是奇怪的。
感謝