c++ 在QThread中启动QTimer

gab6jxml  于 2023-10-20  发布在  其他
关注(0)|答案(6)|浏览(167)

我正在尝试在特定线程中启动QTimer。但是,计时器似乎没有执行,也没有打印出任何内容。这是与计时器,插槽或线程有关吗?
main.cpp

#include "MyThread.h"
    #include <iostream>
    using namespace std;

    int main(int argc, char *argv[]) {
        MyThread t;
        t.start();
        while(1);
    }

MyThread.h

#ifndef MYTHREAD_H
    #define MYTHREAD_H

    #include <QTimer>
    #include <QThread>
    #include <iostream>

    class MyThread : public QThread {
        Q_OBJECT
    public:
        MyThread();
    public slots:
        void doIt();
    protected:
        void run();
    };

    #endif  /* MYTHREAD_H */

MyThread.cpp

#include "MyThread.h"

    using namespace std;

    MyThread::MyThread() {
        moveToThread(this);
    }

    void MyThread::run() {
        QTimer* timer = new QTimer(this);
        timer->setInterval(1);
        timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
        timer->start();
    }

    void MyThread::doIt(){
        cout << "it works";
    }
xienkqul

xienkqul1#

正如我对you are doing it wrong的评论:
1.您正在将保存线程数据的对象与另一个对象(负责doIt())混合在一起。他们应该分开。
1.在你的例子中没有必要子类化QThread。更糟糕的是,您正在重写run方法,而没有考虑它在做什么。
这部分代码应该足够了

QThread* somethread = new QThread(this);
QTimer* timer = new QTimer(0); //parent must be null
timer->setInterval(1);
timer->moveToThread(somethread);
//connect what you want
somethread->start();

现在(Qt版本>=5)默认情况下,QThread在其run()方法中启动一个事件循环。为了在线程中运行,你只需要移动对象。Read the doc...

wnvonmuf

wnvonmuf2#

m_thread = new QThread(this);
QTimer* timer = new QTimer(0); // _not_ this!
timer->setInterval(1);
timer->moveToThread(m_thread);
// Use a direct connection to whoever does the work in order
// to make sure that doIt() is called from m_thread.
worker->connect(timer, SIGNAL(timeout()), SLOT(doIt()), Qt::DirectConnection);
// Make sure the timer gets started from m_thread.
timer->connect(m_thread, SIGNAL(started()), SLOT(start()));
m_thread->start();
a2mppw5e

a2mppw5e3#

QTimer只能在有事件循环的线程中工作。
http://qt-project.org/doc/qt-4.8/QTimer.html
在多线程应用程序中,您可以在任何具有事件循环的线程中使用QTimer。要从非GUI线程启动事件循环,请使用QThread::exec()。Qt使用计时器的线程关联来确定哪个线程将发出timeout()信号。正因为如此,您必须在其线程中启动和停止计时器;不可能从另一个线程启动计时器。

csbfibhn

csbfibhn4#

您可以使用emit信号并在emitted slot函数中启动计时器
main.cpp

#include "MyThread.h"
#include <iostream>
using namespace std;

int main(int argc, char *argv[]) {
    MyThread t;
    t.start();
    while(1);
}

MyThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QTimer>
#include <QThread>
#include <iostream>

class MyThread : public QThread {
    Q_OBJECT
public:
    MyThread();
    QTimer *mTimer;
signals:
   start_timer();
public slots:
    void doIt();
    void slot_timer_start();
protected:
    void run();
};

#endif  /* MYTHREAD_H */

MyThread.cpp

#include "MyThread.h"

using namespace std;

MyThread::MyThread() {
    mTimer = new QTimer(this);
    connect(this,SIGNAL(start_timer()),this, SLOT(slot_timer_start()));
    connect(mTimer,SIGNAL(timeout()),this,SLOT(doIt()));

}

void MyThread::run() {
    emit(start_timer());
    exec();
}

void MyThread::doIt(){
    cout << "it works";
}
void MyThread::slot_timer_start(){
    mTimer->start(1000);
}
ssgvzors

ssgvzors5#

你需要一个事件循环来拥有计时器。下面是我如何用我的代码解决同样的问题:

MyThread::MyThread() {
}

void MyThread::run() {
    QTimer* timer = new QTimer(this);
    timer->setInterval(1);
    timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
    timer->start();

    /* Here: */
    exec();             // Starts Qt event loop and stays there
   // Which means you can't have a while(true) loop inside doIt()
   // which instead will get called every 1 ms by your init code above.
}

void MyThread::doIt(){
    cout << "it works";
}

以下是其他海报都没有提到的相关文档:
int QCoreApplication::exec()**
进入主事件循环并等待直到调用exit()。返回设置为exit()的值(如果通过quit()调用exit(),则为0)。需要调用此函数来启动事件处理。主事件循环接收来自窗口系统的事件并将这些事件分派给应用程序小部件。要使应用程序执行空闲处理(即执行一个特殊的功能,每当有没有挂起的事件),使用QTimer与0超时。使用processEvents()可以实现更高级的空闲处理方案。

0tdrvxhp

0tdrvxhp6#

我创建了一个在lambda函数中调用计时器的示例:

#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QDebug>
#include <memory>

int main(int argc, char** argv)
{
    QCoreApplication app(argc, argv);

    QThread* thread = new QThread(&app);
    QObject::connect(thread, &QThread::started, [=]()
    {
        qInfo() << "Thread started";
        QTimer* timer1 = new QTimer(thread);
        timer1->setInterval(100);
        QObject::connect(timer1, &QTimer::timeout, [=]()
        {
            qInfo() << "Timer1 " << QThread::currentThreadId();
        });
        timer1->start();
    });
    thread->start();

    QTimer timer2(&app);
    QObject::connect(&timer2, &QTimer::timeout, [=]()
    {
        qInfo() << "Timer2 " << QThread::currentThreadId();
    });
    timer2.setInterval(100);
    timer2.start();

    return app.exec();
}

相关问题