2016-11-12 45 views
-2

有此幾乎遺留代碼,涉及一個簡單的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%的系統上差不多半秒是奇怪的。

感謝

回答

-1

考慮到問題的日誌調用,在定時器線程的Execute程序,如果他們最終寫入日誌文件在同一個線程,這將阻止,直到寫操作完成。由於在第一次寫入操作之前檢索到開始時間,因此日誌間隔不僅包含等待時間(WaitForSingleObject),還包含第一次寫入操作。這可以解釋一般偏向30ms而不是20ms。行爲異常的I/O子系統或擁塞也可以解釋偶爾的延長時間段。

檢索等待操作前的開始時間,但不寫入。等待呼叫返回後寫入開始和結束時間。然後日誌會更準確地反映等待時間,最有可能的是延長的延遲將會變成I/O限制。 WaitForSingleObject不太可能不準確。

也考慮卸載日誌寫入到工作線程。