带有超时的WaitForSingleObject会在超时后返回很长时间
这几乎是遗留代码,涉及一个简单的TThread,用作定时器,基于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
日志功能以格式打印NOW的值,$ 1130是当前线程,llDebug是日志级别。 这两个调用之间没有记录(日志文件是“功能”/“模块”)
在这种情况下,等待时间高达959毫秒!
FEvent成员是在主线程中创建的(就像线程计时器本身一样):
FEvent := CreateEvent(nil, false, false, nil);
所以线程本身不会创建窗口,也不会使用COM或类似的东西。 如果SomeMethod会使用这种方法,它将在一个Synchronized调用中,以便在主线程中执行。 然而,对于这个特定的测试,SomeMethod只是在TImage上绘制。
该代码计算FInterval为20 ms。 该线程大约每30/31 ms触发一次,最有可能是由于Windows计时器分辨率。
我们有一个客户运行Windows 10,WaitForSingleObject()每隔几分钟(相隔好几分钟)就会在400+ ms以后才会返回。
SomeMethod在1 ms内执行,因为它没有做太多处理。
我们不需要高分辨率的计时器,因为当前的代码在其他地方都能正常工作,并且每30ms一次就足够了,即使是10-15毫秒的“错误”也是如此。
计时器控制一堆操作,这就是为什么它以大约20ms的间隔执行的原因,但是对于这个问题,我们已经消除了其他所有操作(显式地),只剩下1个操作正在运行,这就是我们如何调试它并查看WaitForSingleObject( )每隔几分钟400+毫秒后不会返回。
在WaitForSingleObject()之前有一个日志调用,并且之后有一个日志调用(也记录了间隔),所以即使间隔为20ms,WaitForSingleObject()也会在400 ms以上返回。 如预期的那样,日志记录显示WaitForSingleObject()的返回值为WAIT_TIMEOUT。
问题是:WaitForSingleObject()中可能导致这种行为的原因是什么? 我的意思是,由于CPU繁忙,线程太多(而不是此应用中的情况),但由于峰值负载小于30%的系统几乎半秒,我可以理解额外的几个ms,这很奇怪。
谢谢
考虑到问题中的日志记录调用,在计时器线程的Execute
过程中,如果它们最终在同一个线程中写入日志文件,则在写入操作完成之前,它会阻塞。 由于在第一次写入操作之前检索到开始时间,因此日志间隔不仅包含等待时间( WaitForSingleObject
),还包含第一次写入操作。 这可以解释一般偏向30ms而不是20ms。 行为异常的I / O子系统或拥塞也可以解释偶尔的延长时间段。
在等待操作之前检索开始时间,但不要写入。 等待呼叫返回后写入开始和结束时间。 然后日志会更准确地反映等待时间,最有可能的是延长的延迟将会变成I / O限制。 WaitForSingleObject
不太可能不准确。
另外考虑将日志写入卸载到工作线程。
链接地址: http://www.djcxy.com/p/62483.html上一篇: WaitForSingleObject with timeout returns long after the timeout