Win32 API的计时器 [英] Win32 API timers

查看:518
本文介绍了Win32 API的计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用的系统定时器(时钟()函数,见time.h中),以某个时间串口和USB通讯科。所有我需要的是约1毫秒accurace。我注意到的第一件事是,个别次能进能出(正负)为10ms。时序一些较小的事件导致了一般的时间随着事件的推移。聚合时机稍好。在MSDN等有点根的后,我整个定时器绊倒在windows多媒体库(timeGetTime(),见MMSYSTEM.H)。这是体面的精度1ms的水平要好得多。

怪诞再发生了,在最初(有用的时序可爱日志)工作flawlessy天它都去豌豆形如这个API也开始出现这个奇怪的粒度(而不是一堆小通讯科的消息服用3毫秒,2毫秒,3毫秒,2毫秒,3ms的等它出来为0毫秒,0毫秒,0毫秒,0毫秒,15毫秒等重新启动PC恢复例正常accuarce但在某些不确定的时间(后一个小时左右)的anomoly返回。

任何人有任何想法或如何得到这个级别的Windows XP计时精度的建议(32位专业版,使用Visual Studio 2008)。

我的小计时类:

 类TMMTimer
{
上市:
    TMMTimer(无符号长毫秒);
    TMMTimer();    void清除(){is_set = FALSE; }
    空集(无符号长毫秒= 0);    布尔过期();
    无符号长消逝();私人的:
    无符号时长;
    INT ROLL_OVER;
    布尔is_set;
};/ **主要构造。
 * /
TMMTimer :: TMMTimer()
{
    is_set = FALSE;
}
/ **主要构造。
 * /
TMMTimer :: TMMTimer(无符号长毫秒)
{
    集(毫秒);
}
/ **设置计时器。
 *
 * @note这将定时器设置为在未来的某一时刻。
 *由于计时器可以绕功能包设置一个
 *此条件由所检查的翻转标志
 *过期的成员函数。
 * /
无效TMMTimer ::设为(无符号​​长毫秒/ * = 0 * /)
{
    无符号长今= timeGetTime(); //系统毫秒计数器。    当= NOW +毫秒;    如果(当<现)
        ROLL_OVER = 1;
    其他
        ROLL_OVER = 0;    is_set = TRUE;
}
/ **检查定时器是否过期。
 *
 *如果过期,否则为假@return返回true。
 *
 *如果计时器从未设置@note又返回true。注意,这
 *函数可以处理的情况时,系统定时器
 *翻转(每47.9天约)。
 * /
布尔TMMTimer ::过期()
{
    如果(!is_set)
        返回true;    无符号长今= timeGetTime(); //系统毫秒计数器。    如果(现>在)
    {
        如果(!ROLL_OVER)
        {
            is_set = FALSE;
            返回true;
        }
    }
    其他
    {
        如果(ROLL_OVER)
            ROLL_OVER = FALSE;
    }    返回false;
}
/ **返回自定时器超时经过的时间。
 *
 *以毫秒为单位@return时间,0,如果计时器从未设置。
 * /
无符号长TMMTimer ::消逝()
{
    如果(!is_set)
        返回0;    返回timeGetTime() - 当;
}


解决方案

你叫 timeBeginPeriod(1); 来设置多媒体分辨率为1毫秒?多媒体计时器分辨率是系统全局,因此,如果你没有自己的设置,有机会,你开始别的呼吁之后,那么当别的东西叫 timeEndPeriod(),分辨率又回到了系统默认的(通常是10毫秒,如果没有记错)。

还有人建议使用 QueryPerformanceCounter的()。这是否有更高的分辨率,但你仍然需要小心。根据所涉及的内核,它可以/将使用86 RDTSC功能,这是个指令周期的64位计数器。是好还是坏,一个CPU的时钟速率变化(始于在笔记本电脑,但现在是常见的几乎无处不在)的时钟之间的关系计算和墙壁正确的时间随着时钟速度变化上。如果没有记错,如果强制Windows的假设安装有多个物理处理器(不仅仅是多核心),你会得到一个内核中, QueryPerformanceCounter的()将读取主板的1.024 MHz时钟来代替。这降低了分辨率相比,CPU时钟,但至少速度常数(如果你只需要1毫秒的分辨率,它应该是绰绰有余反正)。

I was using the system timer (clock() function, see time.h) to time some serial and USB comms. All I needed was approx 1ms accurace. The first thing I noticed is that individual times can be out (plus or minus) 10ms. Timing a number of smaller events led to less accurate timing as events went by. Aggregate timing was slightly better. After a bit of a root on MSDN etc I stumbled across the timer in windows multi-media library (timeGetTime(), see MMSystem.h). This was much better with decent accuracy to the 1ms level.

Weirdness then ensued, after initially working flawlessy for days (lovely logs with useful timings) it all went pearshaped as this API also started showing this odd granularity (instead of a bunch of small comms messages taking 3ms,2ms,3ms,2ms, 3ms etc. it came out as 0ms, 0ms, 0ms, 0ms, 15ms etc. Rebooting the PC restored nomal accuarce but at some indeterminate time (after an hour or so) the anomoly returned.

Anyone got any idea or suggestions of how to get this level of timing accuracy on Windows XP (32bit Pro, using Visual Studio 2008).

My little timing class:

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;
}

解决方案

Did you call timeBeginPeriod(1); to set the multimedia resolution to 1 millisecond? The multimedia timer resolution is system-global, so if you didn't set it yourself, chances are that you started after something else had called it, then when that something else called timeEndPeriod(), the resolution went back to the system default (which is normally 10 ms, if memory serves).

Others have advised using QueryPerformanceCounter(). This does have much higher resolution, but you still need to be careful. Depending on the kernel involved, it can/will use the x86 RDTSC function, which is a 64-bit counter of instruction cycles. For better or worse, on a CPU whose clock rate varies (which started on laptops, but is now common almost everywhere) the relationship between the clock count and wall time varies right along with the clock speed. If memory serves, if you force Windows to install with the assumption that there are multiple physical processors (not just multiple cores), you'll get a kernel in which QueryPerformanceCounter() will read the motherboard's 1.024 MHz clock instead. This reduces resolution compared to the CPU clock, but at least the speed is constant (and if you only need 1 ms resolution, it should be more than adequate anyway).

这篇关于Win32 API的计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆