Démarrage De QTimer Dans Un QThread

j'essaie de démarrer un QTimer dans un thread spécifique. Cependant, la minuterie ne semble pas fonctionner et rien n'est imprimé. Est-ce que ça a quelque chose à voir avec la minuterie, la fente ou le fil?

main.rpc

    #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.rpc

    #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";
    }
14
demandé sur sandwood 2012-05-08 08:16:21

6 réponses

Comme je l'ai commenté (plus d'informations dans le lien) vous faites du mal :

  1. vous mélangez l'objet contenant les données du thread avec un autre objet (responsable de doIt()). Ils doivent être séparés.
  2. il n'y a pas besoin de sous-classe QThread dans votre cas. Pire, vous écrasez la run méthode sans aucune considération de ce qu'elle faisait.

cette portion de code devrait suffire

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

maintenant (version Qt >= 4.7) par défaut QThread démarre une boucle d'événement dans sa run() méthode. Afin de s'exécuter dans un thread, il vous suffit de déplacer l'objet. lire le doc...

24
répondu UmNyobe 2014-10-02 10:30:53
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();
11
répondu Andreas Haferburg 2016-07-26 09:42:08

QTimer ne fonctionne que dans un thread qui a une boucle d'événements.

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

dans les applications multithreaded, vous pouvez utiliser QTimer dans n'importe quel thread qui a une boucle d'événement. Pour lancer une boucle d'événement à partir d'un thread non-GUI, utilisez QThread::exec(). Qt utilise l'affinité du thread pour déterminer quel thread émettra le signal timeout (). Pour cette raison, vous devez démarrer et arrêter le minuteur dans son fil; il n'est pas possible de démarrer une minuterie à partir d'un autre thread.

9
répondu Brian Roach 2012-05-08 04:19:02

vous pouvez utiliser le signal d'émission et démarrer la minuterie à l'intérieur de la fonction de fente émise

main.rpc

#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.rpc

#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);
}
1
répondu pathaleswar 2017-09-14 13:03:42

Vous avez besoin d'une boucle pour avoir compteurs. Voici comment j'ai résolu le même problème avec mon code:

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

Voici la question de la documentation qu'aucun des autres affiches mentionné:

int QCoreApplication:: exec ()

entre dans la boucle d'événement principal et attend que exit() soit appelé. Retourner la valeur qui a été définie pour la sortie() (qui est 0 si exit() est appelée par quitter.))( Il est nécessaire d'appeler cette fonction pour commencer événement manutention. La boucle principale reçoit les événements de la fenêtre système et envoie ceci aux widgets d'application. Pour faire de votre application effectuer un traitement inactif (c.-à-d. exécuter une fonction spéciale chaque fois qu'il n'y a pas d'événements en cours), utilisez un QTimer avec 0 timeout. Des schémas de traitement plus avancés peuvent être obtenus en utilisant processEvents ().

0
répondu Daniel Donnelly 2017-10-16 20:06:53

j'ai créé un exemple qui appelle le timer dans une fonction 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();
}
0
répondu Fernando 2018-04-23 19:30:25