有此几乎遗留代码,涉及一个简单的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%的系统上差不多半秒是奇怪的。
感谢