自学内容网 自学内容网

QT 线程计时器

qt自带的计时器QTimer是与界面主线程绑定在一起的,如果操作界面有可能会影响计时器的执行,所以查找一些资料写了一个长期运行的线程计时器。

1.线程类的头文件

#ifndef WORKTH_H
#define WORKTH_H

#include <QDebug>
#include <QThread>
#include <QObject>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <thread>

class WorkTh  : public QObject
{
    Q_OBJECT

private:
    #define SLEEP(a) std::this_thread::sleep_for(std::chrono::milliseconds(a));
    void delay(int msec);

signals:
    void workFinished(const qint64 cycleTime);

public:
    WorkTh(QObject* parent = nullptr);
    ~WorkTh();
    void doWork();

    std::atomic<bool> m_isquit;
    std::atomic<bool> m_ispuse;
    std::mutex m_mutex;
    std::condition_variable m_cond;
};

#endif

2.线程类,提供两种计算时差的方式,可根据需求自己选择

#include "WorkTh.h"
#include <QWaitCondition>
#include <qelapsedtimer.h>

WorkTh::WorkTh(QObject *parent)
    : QObject(parent)
{
    m_isquit = false;
    m_ispuse = false;

    p_zcobj = new ZcObj(parent);

}

void WorkTh::doWork()
{
    qint64 argIntimestamp64;
    qint64 finishtimestamp64;
    qint64 currenttimestamp64;
    qint64 intervaltimestamp64;

    qint64 timestamp64;
    qint64 lasttimestamp64=0;
    qint64 nexttimestamp64 = 0;
    QElapsedTimer timer;


    timer.start();
    while (!m_isquit)
    {
        //方式一,误差很小,cpu占用低 推荐
        argIntimestamp64 = QDateTime::currentMSecsSinceEpoch();

        std::unique_lock<std::mutex> locker(m_mutex);
        while (m_ispuse) m_cond.wait(locker);
        if (m_isquit)return;

        //此处可写业务逻辑

        emit workFinished(argIntimestamp64);

        intervaltimestamp64 =  argIntimestamp64 + 300- QDateTime::currentMSecsSinceEpoch();
        //300ms执行一次
        if (intervaltimestamp64 > 0)
        {
            delay(intervaltimestamp64);
        }   

        //方式二,几乎没有误差,cup占用高
        //while (timer.elapsed() >= SIB_MAIN_CYCLE)
        //{
        //    timer.restart();
        //    timestamp64 = QDateTime::currentMSecsSinceEpoch();

        //    std::unique_lock<std::mutex> locker(m_mutex);
        //    while (m_ispuse) m_cond.wait(locker);
        //    if (m_isquit)return;

        //   
        //   //此处可写业务逻辑
        //    emit workFinished(timestamp64);
        //}
    }

}

void WorkTh::delay(int msec)
{   
    QEventLoop loop;
    QTimer::singleShot(msec, &loop, SLOT(quit()));
    loop.exec();
}

WorkTh::~WorkTh()
{

}

3.计时器使用

    QThread p_thread = new QThread();
    QThread p_work = new WorkTh();
    p_work->moveToThread(p_thread);

    //连接信号槽 如果参数是自定义的需要使用qRegisterMetaType进行声明
    connect(p_thread, &QThread::started, p_work, &WorkTh::doWork);
    connect(p_work, SIGNAL(workFinished(qint64)), this, SLOT(oneLogicMain(qint64)));


原文地址:https://blog.csdn.net/shu19880720/article/details/140120301

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!