Вопрос по multithreading, c++ – Запуск QTimer в QThread

14

Я пытаюсь запустить 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";
    }
Ссылка была изменена на:blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong donturner
почему вы не создаете QApplication? Kunal
это не так, как все должно быть сделано.read this post UmNyobe
Ссылка снова изменилась:blog.qt.io/blog/2010/06/17/youre-doing-it-wrong Andreas Haferburg

Ваш Ответ

6   ответов
0

#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();
}
0

чтобы иметь таймеры. Вот как я решил ту же проблему с моим кодом:

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()

Enters the main event loop and waits until exit() is called. Returns the value that was set to exit() (which is 0 if exit() is called via quit()). It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More advanced idle processing schemes can be achieved using processEvents().

9

QTimer работает только в потоке, в котором есть цикл обработки событий.

http://qt-project.org/doc/qt-4.8/QTimer.html

In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.

Создайте QApplication, затем создайте ваш поток
Я пытался добавить exec () в метод run, но получаю QEventLoop: невозможно использовать без QApplication. Tudor Pascu
1

Вы можете использовать сигнал излучения и запустить таймер внутри функции излучаемого слота

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

вы делаете это неправильно:

You are mixing the object holding thread data with another object (responsible of doIt()). They should be separated. There is no need to subclass QThread in your case. Worse, you are overriding the run method without any consideration of what it was doing.

Этой части кода должно быть достаточно

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 & gt; = 4.7) по умолчаниюQThread запускает цикл событий в егоrun() метод. Для запуска внутри потока вам просто нужно переместить объект.Прочитайте документ ...

подключите сигнал к слоту таймераstart() и вызвать сигнал
а именноconnect(somethread, SIGNAL(started()), timer, SLOT(start()))
Если я хочу остановить поток и таймер, безопасно ли вызывать thread.quit () и после этого thread.wait ()? "Что-нибудь"? освободить память для объекта QTimer?
Как я могу запустить этот таймер вне какой-либо темы (в текущей теме)? Должен ли я использовать QueuedConnection?
нет, поток освобождает что-либо. Применяется правило Qobject без родителя, что означает, что вы должны удалить в какой-то момент после thread.wait (). Обратите внимание, что таймер не обязательно должен быть указателем, может быть объектом напрямую (и членом вызывающей стороны) или общим указателем.
11
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();
@Stormenet Какой-то объект со слотомdoIt() он должен выполнять работу (в созданном потоке) всякий раз, когда срабатывает таймер.
Мне непонятно, чтоworker является.

Похожие вопросы