再次诚请教高精度定时器(定时而不能占CPU)

时间:2020-12-02 08:51:53
诚心请教各位高手:
  SetTimer可以用作定时器,可是精度较低,大概15毫秒调用一次,请问有没有比此函数精度更高的方法,关键是不能占用CPU,多谢各位!

16 个解决方案

#1


有不占CPU的操作吗

#2


用多媒体定时间器吧,可以精确到1毫秒
UINT TimerScanStart(LPTIMECALLBACK fptc,int TimeCycle,BOOL bTime_OneShot)
{
UINT TimeID = 0;
TIMECAPS tc;
if(::timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
{
DWORD wAccuracy;
wAccuracy=min(max(tc.wPeriodMin,TIMER_ACCURACY),tc.wPeriodMax);
if(timeBeginPeriod(wAccuracy) == TIMERR_NOERROR )
{
// 参数 TIME_PERIODIC: 周期执行
if(TimeCycle >= wAccuracy && TimeCycle <= tc.wPeriodMax)
{
if(bTime_OneShot)
{//只执行一次
TimeID = ::timeSetEvent(TimeCycle,wAccuracy,fptc,(DWORD)this,TIME_ONESHOT);
}
else
{//周期执行
TimeID = ::timeSetEvent(TimeCycle,wAccuracy,fptc,(DWORD)this,TIME_PERIODIC);
}
}
timeEndPeriod(wAccuracy);
}

}
return TimeID ;
}

#3


正点,过会试试。我指的不占CPU就是定时器“休眠”过程中,
它所在的线程能够让出系统资源。如Sleep()就是不占CPU的延时,
但我需要比它更精确的延时。各位高手,继续啊,不要停,急用

#4


CreateWaitableTimer()创建内核定时器,可以帮你实现精度到最少至100ns的定时器,
够了吧。

#5


timeSetEvent 只能用16个吧

#6


timeSetEvent 确实只能用16个

#7


http://www.vckbase.com/document/viewdoc/?id=1301

#8


timeSetEvent 确实只能用16个

不错,在一个进程中,真是很恶心!

#9


核实下:setTimer好象是55ms的精度  

好像system.sys中隐藏了某个定时函数(就是在Windows.h中没有给出声明),待我回去查查

#10


恩?一个进程只能有16个,哪儿说的,或者是自己试出来的,还是自己跟踪出来的?我不知道,谁给解释一下

#11


当然是WaitableTime,精度能满足,还保持线程等待状态

#12


WaitableTimer

#13


我觉得就算是通过线程、事件Event也不要去碰什么定时器 会死的惨兮兮的

#14


性能计数器更精确些,不过不占用cpu怎么测量啊

#15


楼主有没有想过,在windows这种多线程非实时操作系统中,实现精度为1ms的定时,几乎是不可能的么?
    即使你用多媒体定时器,比如,在一个线程A中定义一个每1ms触发一次的定时器,假如始终都是这一个线程占有cpu时间的话,那自然可以实现1ms精确定时。但在多进程的分时操作系统中,有可能线程A在定时器开始计时后,A被阻塞,转而执行其他高优先级的线程,系统并不能保证在1ms时间到了后,一定能马上把cpu时间切换到A,因此也就无法执行你的定时器回调函数。或许等到线程A获得cpu时间时,早已经过了1ms的时间了。
    这并不是系统的缺陷,而是多线程非实时系统的固有特性。
   因此,我觉得楼主在windows系统中极端的追求这种高精度并且不耗cpu时间的定时,是不大可能的。

#16


楼上的有道理,你就不访这样吧
hEvent=CreateEvent(...);
WaitForSingleObject(hEvent,你的定时);
CloseHandle(hEvent);

#1


有不占CPU的操作吗

#2


用多媒体定时间器吧,可以精确到1毫秒
UINT TimerScanStart(LPTIMECALLBACK fptc,int TimeCycle,BOOL bTime_OneShot)
{
UINT TimeID = 0;
TIMECAPS tc;
if(::timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
{
DWORD wAccuracy;
wAccuracy=min(max(tc.wPeriodMin,TIMER_ACCURACY),tc.wPeriodMax);
if(timeBeginPeriod(wAccuracy) == TIMERR_NOERROR )
{
// 参数 TIME_PERIODIC: 周期执行
if(TimeCycle >= wAccuracy && TimeCycle <= tc.wPeriodMax)
{
if(bTime_OneShot)
{//只执行一次
TimeID = ::timeSetEvent(TimeCycle,wAccuracy,fptc,(DWORD)this,TIME_ONESHOT);
}
else
{//周期执行
TimeID = ::timeSetEvent(TimeCycle,wAccuracy,fptc,(DWORD)this,TIME_PERIODIC);
}
}
timeEndPeriod(wAccuracy);
}

}
return TimeID ;
}

#3


正点,过会试试。我指的不占CPU就是定时器“休眠”过程中,
它所在的线程能够让出系统资源。如Sleep()就是不占CPU的延时,
但我需要比它更精确的延时。各位高手,继续啊,不要停,急用

#4


CreateWaitableTimer()创建内核定时器,可以帮你实现精度到最少至100ns的定时器,
够了吧。

#5


timeSetEvent 只能用16个吧

#6


timeSetEvent 确实只能用16个

#7


http://www.vckbase.com/document/viewdoc/?id=1301

#8


timeSetEvent 确实只能用16个

不错,在一个进程中,真是很恶心!

#9


核实下:setTimer好象是55ms的精度  

好像system.sys中隐藏了某个定时函数(就是在Windows.h中没有给出声明),待我回去查查

#10


恩?一个进程只能有16个,哪儿说的,或者是自己试出来的,还是自己跟踪出来的?我不知道,谁给解释一下

#11


当然是WaitableTime,精度能满足,还保持线程等待状态

#12


WaitableTimer

#13


我觉得就算是通过线程、事件Event也不要去碰什么定时器 会死的惨兮兮的

#14


性能计数器更精确些,不过不占用cpu怎么测量啊

#15


楼主有没有想过,在windows这种多线程非实时操作系统中,实现精度为1ms的定时,几乎是不可能的么?
    即使你用多媒体定时器,比如,在一个线程A中定义一个每1ms触发一次的定时器,假如始终都是这一个线程占有cpu时间的话,那自然可以实现1ms精确定时。但在多进程的分时操作系统中,有可能线程A在定时器开始计时后,A被阻塞,转而执行其他高优先级的线程,系统并不能保证在1ms时间到了后,一定能马上把cpu时间切换到A,因此也就无法执行你的定时器回调函数。或许等到线程A获得cpu时间时,早已经过了1ms的时间了。
    这并不是系统的缺陷,而是多线程非实时系统的固有特性。
   因此,我觉得楼主在windows系统中极端的追求这种高精度并且不耗cpu时间的定时,是不大可能的。

#16


楼上的有道理,你就不访这样吧
hEvent=CreateEvent(...);
WaitForSingleObject(hEvent,你的定时);
CloseHandle(hEvent);