[QT编程系列-42]: QT定时器

目录

第1章 QT下的定时器

1.1 主要的对象

1.2 QTTimer定时的特点

1.3 QT高精度定时器QElapsedTimer: 计时

第2章 Windows操作系统下的高性能定时器

2.1 时钟分辨率

2.2 两种来实现高性能定时器:

2.3 timeSetEvent用法

第3章 timeSetEvent和QTimer比较

3.1 概述

3.2 精度比较


第1章 QT下的定时器

1.1 主要的对象

QT框架中提供了两种类型的定时器:QTimerQTimerEvent

  1. QTimer:QTimer是QT提供的一个高级定时器类,它基于QObject类,并且可以与事件循环一起工作。QTimer提供了灵活的定时器功能,可以执行单次或周期性的定时任务。

    使用QTimer,你可以执行以下操作:

    • 启动和停止定时器。
    • 设置定时器的间隔时间,即触发定时器事件的时间间隔。
    • 设置定时器的类型,包括单次执行和重复执行。
    • 与QObject的槽函数或lambda表达式连接,触发定时器事件时执行特定的操作。

    以下是使用QTimer的示例代码:

    QTimer *timer = new QTimer(this);
    
    // 设置定时器间隔时间
    timer->setInterval(1000); // 每隔1秒触发一次定时器事件
    
    // 连接定时器事件和槽函数
    // 定时器到期后,自动发送timeout信号
    connect(timer, &QTimer::timeout, this, &MyClass::handleTimerEvent);
    
    // 启动定时器
    timer->start();
    
  2. QTimerEvent:QTimerEvent是QT中的一个事件类,它用于处理与QTimer相关的事件。在继承了QObject的类中,可以重写QObject的虚函数timerEvent(QTimerEvent* event)来处理定时器事件。

    以下是使用QTimerEvent的示例代码:

    void MyClass::timerEvent(QTimerEvent *event)
    {
        if (event->timerId() == timerId) {
            // 处理定时器事件的逻辑
        }
        QObject::timerEvent(event);
    }
    

QTimer是较为常用和方便的定时器类,它提供了简单的接口和信号槽机制来处理定时器事件。而QTimerEvent则更加底层,需要手动重写timerEvent函数,并进行定时器事件的处理逻辑。开发者可以根据具体需求选择使用哪种定时器类型。

1.2 QTTimer定时的特点

QT定时器的特点如下:

  1. 简单易用:QT定时器提供了简洁、易于使用的接口,使开发人员可以轻松创建和管理定时器对象。

  2. 灵活性:QT定时器支持各种类型的定时器,包括单次定时器、重复定时器和单次重叠定时器,可以根据具体需求选择合适的类型。

  3. 高精度:QT定时器能够提供高精度的计时能力,通常以毫秒级别为单位。这样,开发人员可以实现精确的定时任务,满足应用程序的需求。QT定时器的最小精度是毫秒。

  4. 线程安全:QT定时器可以安全地在多线程环境中使用。它提供了线程安全的机制,使定时器能够在不同线程中创建、启动和停止,以满足多线程应用程序的需求

  5. 与信号槽机制集成:QT定时器可以与QT的信号槽机制无缝集成。开发人员可以将定时器的超时信号(timeout)与其他对象的槽函数或lambda表达式连接,实现灵活的定时任务逻辑。

  6. 多平台支持:QT定时器在不同平台的行为表现一致,无论是在Windows、MacOS、Linux等操作系统上,还是在嵌入式系统上。这保证了代码在不同平台下的可移植性和一致性。

  7. 高度集成:QT定时器可以与QT框架中的其他组件高度集成,如GUI控件、网络功能等。这使得开发人员可以将定时器与其他功能相结合,实现丰富的交互和功能。

综上所述,QT定时器具有简单易用、灵活性、高精度、线程安全、信号槽机制集成、多平台支持和高度集成等特点。它是QT开发中管理和执行定时任务的重要组件。无论是创建简单的定时器还是实现复杂的定时任务逻辑,QT定时器能够有效地满足开发人员的需求。

1.3 QT高精度定时器QElapsedTimer: 计时

QElapsedTimer主要用于衡量时间间隔,而不是作为实时定时器。它提供了对时间的高分辨率测量,但不具备定时器的触发和重复执行功能。

在QT中,针对高性能定时器需求,可以使用Qt的高分辨率定时器类QElapsedTimer。QElapsedTimer提供了纳秒级别的精确计时功能,适用于需要精确计时高性能定时的应用场景。

使用QElapsedTimer进行高性能定时,可以按照以下步骤:

  1. 创建和启动QElapsedTimer对象:

    QElapsedTimer timer;
    timer.start();
    
  2. 执行代码或任务:

    // 执行需要计时的代码或任务
    
  3. 获取经过的时间:

    qint64 elapsedTime = timer.nsecsElapsed();  // 获取经过的纳秒数
    
    // 转换为所需时间单位(如毫秒)
    qreal elapsedMilliseconds = static_cast(elapsedTime) / 1000000.0;
    

示例代码:

#include 
#include 
#include 

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QElapsedTimer timer;
    timer.start();
    
    // 执行需要计时的代码或任务
    for (int i = 0; i < 10000000; ++i) {
        // 一些操作
    }
    
    qint64 elapsedTime = timer.nsecsElapsed();
    qreal elapsedMilliseconds = static_cast(elapsedTime) / 1000000.0;
    qDebug() << "Elapsed time:" << elapsedMilliseconds << "ms";
    
    return a.exec();
}

使用QElapsedTimer类可以实现高性能的定时任务,尤其适用于需要测量代码执行时间或实现精确计时的应用程序。它提供了方便的接口来获取经过的纳秒数并进行单位转换,以满足不同精度的计时需求。

QElapsedTimer是Qt提供的一个高精度计时器类,用于测量时间间隔。它可以提供纳秒级别的精确计时,并且不受系统时间的影响。

以下是使用QElapsedTimer的示例代码:

#include 
#include 
#include 

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QElapsedTimer timer;
    timer.start();

    // 执行需要计时的代码或任务
    for (int i = 0; i < 10000000; ++i) {
        // 一些操作
    }

    qint64 elapsedTime = timer.nsecsElapsed();
    qreal elapsedMilliseconds = static_cast(elapsedTime) / 1000000.0;
    qDebug() << "Elapsed time:" << elapsedMilliseconds << "ms";

    return a.exec();
}

在上面的示例中,创建了QElapsedTimer对象timer,并使用timer.start()开始计时。

然后,在需要计时的代码或任务执行之后,调用timer.nsecsElapsed()获取经过的纳秒数

如果需要将纳秒数转换为其他单位,可以使用除以适当的倍数来转换,例如将纳秒转换为毫秒,需要除以1000000。

最后,可以打印或使用获得的时间间隔进行后续处理。

请注意,QElapsedTimer的计时器受到系统的性能和精度限制,因此在不同的系统上可能会有所不同。但相对于Qt的QTimer类,QElapsedTimer提供了更高精度的测量能力,适用于需要准确计时的场景。

第2章 Windows操作系统下的高性能定时器

2.1 时钟分辨率

在Windows操作系统中,时钟分辨率是指操作系统提供的计时器的最小时间间隔。它决定了定时器的精度和能够设置的最小延迟时间。

Windows操作系统的默认时钟分辨率是15.6毫秒(ms),即0.0156秒。这意味着最小的延迟时间或定时器触发间隔是15.6毫秒。

然而,可以通过调用timeBeginPeriod函数来改变时钟分辨率。timeBeginPeriod函数允许应用程序请求更高的时钟精度。通常,较低的时钟分辨率会导致更高的系统资源消耗,因此应该根据实际需求进行权衡和使用。

请注意,更高的分辨率并不一定意味着更高的准确性。时钟分辨率受到系统硬件和操作系统调度的限制,并且实际的定时器触发时间可能会受到其他因素的影响,例如系统负载、其他进程的优先级、功耗管理等。

在使用时钟分辨率时,请考虑应用程序的需求和系统资源使用,并在必要时恢复默认的时钟分辨率。对于大多数通用应用程序而言,Windows默认的时钟分辨率已经足够使用。如有特定需求,可以使用高分辨率定时器等特定技术来获得更高的精确度和准确性。

2.2 两种来实现高性能定时器:

在Windows操作系统中,可以使用以下两种来实现高性能定时器:

  1. QueryPerformanceCounter QueryPerformanceFrequency 函数:=》计时
    这是Windows操作系统提供的API函数,用于获取高性能计数器的值和频率。高性能计数器提供了一个非常精确的计时方式,可以用来测量短时间间隔的性能。这是通过QueryPerformanceFrequency函数获取计时器的频率(每秒计时器的计数数目),然后使用QueryPerformanceCounter函数获取当前计时器的计数值。

    示例代码:

    LARGE_INTEGER frequency;
    LARGE_INTEGER start;
    LARGE_INTEGER end;
    
    QueryPerformanceFrequency(&frequency);
    QueryPerformanceCounter(&start);
    
    // 执行代码或任务
    
    QueryPerformanceCounter(&end);
    double elapsedTime = (end.QuadPart - start.QuadPart) * 1000.0 / frequency.QuadPart;
    

    使用QueryPerformanceCounter和QueryPerformanceFrequency函数可以获取非常高精度的时间戳,适用于实现精确计时和定时任务,尤其在需要测量代码执行时间或实现实时系统应用程序时。

  2. Multimedia Timers(多媒体定时器):定时
    Windows操作系统还提供了多媒体定时器API,以实现高分辨率低延迟的定时器功能。多媒体定时器允许以毫秒级的精度设置和触发定时器事件,适用于需要高性能定时器功能的多媒体应用程序和实时系统。

    这些API包括timeSetEvent、timeBeginPeriod和timeEndPeriod等函数。其中,timeSetEvent函数用于创建启动定时器,可以指定定时器的触发间隔、回调函数等参数。

    示例代码:

    void CALLBACK TimerCallback(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
    {
        // 定时器事件的处理逻辑
    }
    
    // 设置定时器并启动
    UINT timerId = timeSetEvent(
        period,            // 间隔时间(单位:毫秒)
        resolution,        // 分辨率(单位:毫秒)
        TimerCallback,     // 回调函数
        0,                 // 回调函数参数
        TIME_PERIODIC      // 定时器类型 - 重复执行
    );
    
    // 停止定时器
    timeKillEvent(timerId);
    

    使用多媒体定时器API可以实现高性能的毫秒级别定时器,适用于需要高精度的定时任务,并且对实时性要求较高的应用程序。

无论使用哪种方法,高性能定时器的准确性和精度受到多个因素的影响,包括硬件性能、系统负载等。在实际应用中,应根据实际需求和应用场景选择适合的方法,并进行充分的测试和验证,以确保定时器满足性能要求。

2.3 timeSetEvent用法

Windows API中的timeSetEvent函数用于设置定时器事件。

该函数允许您在指定的时间间隔内定期调用一个回调函数

以下是timeSetEvent函数的用法:

MMRESULT timeSetEvent(
    UINT           uDelay,
    UINT           uResolution,
    LPTIMECALLBACK lpTimeProc,
    DWORD_PTR      dwUser,
    UINT           fuEvent
);

参数说明:

  • uDelay:指定事件触发的延迟时间(以毫秒为单位)。
  • uResolution:指定定时器的最小时间分度。较小的值表示较高的分辨率。通常使用1作为最小分度。
  • lpTimeProc:指向回调函数的指针,当定时器事件触发时将调用该函数。
  • dwUser:用于传递给回调函数的用户定义的值(可选)。
  • fuEvent:事件类型标志,可以是TIME_ONESHOT(定时器只触发一次)或TIME_PERIODIC(定时器定期触发)。

使用示例:

#include 
#include 

void CALLBACK TimerProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    std::cout << "Timer event triggered!" << std::endl;
}

int main()
{
    // 设置一个定时器,每1000毫秒触发一次
    MMRESULT timerId = timeSetEvent(1000, 0, TimerProc, 0, TIME_PERIODIC);
    if (timerId == 0)
    {
        std::cout << "Failed to set timer!" << std::endl;
        return 1;
    }

    // 等待用户按下任意键停止定时器
    std::cout << "Timer started. Press any key to stop." << std::endl;
    std::cin.get();

    // 停止定时器
    MMRESULT result = timeKillEvent(timerId);
    if (result != TIMERR_NOERROR)
    {
        std::cout << "Failed to stop timer!" << std::endl;
        return 1;
    }

    std::cout << "Timer stopped." << std::endl;
    return 0;
}

上述示例代码中,我们创建了一个定时器,每1000毫秒触发一次。当定时器事件被触发时,回调函数TimerProc将被调用。用户可以通过按下任意键来停止定时器。

请注意,在使用timeSetEvent函数后,应使用timeKillEvent函数停止定时器。否则,定时器事件将会持续触发,可能导致不必要的问题。

第3章 timeSetEvent和QTimer比较

3.1 概述

timeSetEvent和QTimer是两个不同的定时器机制,分别对应于Windows平台的原生API和Qt框架中的定时器类。

  1. timeSetEvent:

    • timeSetEvent是Windows API提供的函数,用于设置定时器事件。
    • 它可以在指定的时间间隔内定期调用一个回调函数。
    • timeSetEvent需要手动设置参数,包括延迟时间、事件分辨率、回调函数等。
    • timeSetEvent是使用C/C++编程语言进行调用和使用。
  2. QTimer:

    • QTimer是Qt框架提供的定时器类,封装了定时器的常用操作。
    • 它基于事件循环机制,可以在Qt应用程序中使用。
    • QTimer提供了方便的接口和信号槽机制来处理定时器事件,无需手动设置回调函数。
    • QTimer提供了更高级别的功能,例如单次定时、间隔定时、暂停和重启等。

主要区别:

  • 实现方式不同:timeSetEvent是通过调用Windows API实现的,而QTimer是基于Qt框架提供的定时器类。
  • 参数设置:timeSetEvent需要手动设置参数,包括延迟时间、回调函数等,而QTimer受到Qt框架的封装,提供了更简单的接口和信号槽机制。
  • 平台依赖性:timeSetEvent是Windows特定的API,只能在Windows平台上使用。而QTimer是Qt框架的一部分,可以在跨平台的Qt应用程序中使用。

选择使用timeSetEvent还是QTimer取决于您的开发环境和需求。如果您正在使用Windows平台,并且更倾向于使用原生API和C/C++进行开发,则可以选择timeSetEvent。如果您使用Qt框架,并且希望使用更便捷的接口和信号槽机制,以及跨平台的可移植性,则可以选择QTimer。

3.2 精度比较

在精度方面,timeSetEvent和QTimer可能会有一些差异,具体取决于操作系统硬件的限制。

(1)timeSetEvent:

  • 精度依赖于操作系统提供的时钟分辨率,可以通过设置uResolution参数来控制,最小单位为毫秒。
  • Windows操作系统的时钟分辨率通常为15.6毫秒,即最小分辨率为15.6毫秒。
  • 由于存在系统调度和其他任务的影响,timeSetEvent的实际触发时间可能会有一定的偏差。

(2)QTimer:

  • QTimer基于操作系统和使用的定时器设备驱动,可以实现更高的精度。
  • 在大多数情况下,QTimer的默认精度为10毫秒,即最小分辨率为10毫秒。
  • Qt框架使用操作系统提供的定时器机制(例如Windows下使用Multimedia Timer或定时器线程)来实现定时器功能。
  • QTimer的精度还受到机器负载、操作系统调度和其他因素的影响。

需要注意的是,无论是timeSetEvent还是QTimer,它们都无法提供绝对精确的定时器,因为操作系统和硬件的限制会造成一定的延迟和偏差。如果需要更高精度的定时功能,可能需要使用特定于硬件的定时器库或使用专用硬件设备。

总而言之,对于一般应用场景,QTimer通常具有足够的精度,可以满足大多数需求。但如果对精度要求非常高,例如实时应用或需要更精确时间控制的场景,可能需要使用其他方案来满足需求。

你可能感兴趣的:(编程系列-QT,qt,开发语言)