Tim*_*ing 2 c c++ winapi system timer
我正在使用系统定时器(clock()函数,请参阅time.h)来计算一些串行和USB通信.我需要的只有大约1毫米的准备.我注意到的第一件事是个别时间可以超出(加或减)10毫秒.随着事件的发生,对一些较小的事件进行定时导致时间不准确.总体时间略好一些.在MSDN上有点根后,我偶然发现了Windows多媒体库中的计时器(timeGetTime(),参见MMSystem.h).这对于1ms级别来说具有良好的准确性要好得多.
然后发生了奇怪的事情,经过几天完美无瑕的工作(可爱的日志和有用的时间)这一切都变成了梨形,因为这个API也开始显示这种奇怪的粒度(而不是一堆小通信消息需要3ms,2ms,3ms,2ms,3ms等它出现了0ms,0ms,0ms,0ms,15ms等.重新启动PC恢复了正常的准确性,但在一些不确定的时间(一小时左右之后),anomoly返回.
任何人都对如何在Windows XP(32位Pro,使用Visual Studio 2008)上获得这种级别的计时准确性有任何想法或建议.
我的小时间班:
class TMMTimer
{
public:
TMMTimer( unsigned long msec);
TMMTimer();
void Clear() { is_set = false; }
void Set( unsigned long msec=0);
bool Expired();
unsigned long Elapsed();
private:
unsigned long when;
int roll_over;
bool is_set;
};
/** Main constructor.
*/
TMMTimer::TMMTimer()
{
is_set = false;
}
/** Main constructor.
*/
TMMTimer::TMMTimer( unsigned long msec)
{
Set( msec);
}
/** Set the timer.
*
* @note This sets the timer to some point in the future.
* Because the timer can wrap around the function sets a
* rollover flag for this condition which is checked by the
* Expired member function.
*/
void TMMTimer::Set( unsigned long msec /*=0*/)
{
unsigned long now = timeGetTime(); // System millisecond counter.
when = now + msec;
if (when < now)
roll_over = 1;
else
roll_over = 0;
is_set = true;
}
/** Check if timer expired.
*
* @return Returns true if expired, else false.
*
* @note Also returns true if timer was never set. Note that this
* function can handle the situation when the system timer
* rolls over (approx every 47.9 days).
*/
bool TMMTimer::Expired()
{
if (!is_set)
return true;
unsigned long now = timeGetTime(); // System millisecond counter.
if (now > when)
{
if (!roll_over)
{
is_set = false;
return true;
}
}
else
{
if (roll_over)
roll_over = false;
}
return false;
}
/** Returns time elapsed since timer expired.
*
* @return Time in milliseconds, 0 if timer was never set.
*/
unsigned long TMMTimer::Elapsed()
{
if (!is_set)
return 0;
return timeGetTime()-when;
}
Run Code Online (Sandbox Code Playgroud)
您是否打电话timeBeginPeriod(1);将多媒体分辨率设置为1毫秒?多媒体计时器的分辨率是系统全局的,所以如果你没有自己的设置,有机会,你开始别的呼吁后,那么当别的东西叫timeEndPeriod(),分辨率又回到了系统默认的(这通常是10毫秒,如果内存服务).
其他人建议使用QueryPerformanceCounter().这确实具有更高的分辨率,但您仍需要小心.根据所涉及的内核,它可以/将使用x86 RDTSC函数,该函数是指令周期的64位计数器.无论好坏,在时钟频率变化的CPU上(从笔记本电脑开始,但现在几乎无处不在),时钟计数和挂壁时间之间的关系随时钟速度而变化.如果内存服务,如果强制Windows安装时假设有多个物理处理器(而不仅仅是多个内核),那么你将获得一个内核,QueryPerformanceCounter()它将读取主板的1.024 MHz时钟.与CPU时钟相比,这会降低分辨率,但至少速度是恒定的(如果您只需要1 ms的分辨率,那么它应该是足够的).