2012-05-08 10 views
12

Sto tentando di avviare un QTimer in una thread specifica. Tuttavia, il timer non sembra essere eseguito e non viene stampato nulla. Ha qualcosa a che fare con il timer, lo slot o il thread?Avvio di QTimer in A QThread

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

questo non è il modo in cui le cose dovrebbero essere fatte più. [leggi questo post] (http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/) – UmNyobe

+0

perché non stai creando QApplication? – Kunal

+2

Il collegamento è stato modificato in: http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ – donturner

risposta

20

Come ho commentato (ulteriori informazioni nel link) che si sta facendo male:

  1. si stia mescolando l'oggetto che contiene i dati di thread con un altro oggetto (responsabile doIt()). Dovrebbero essere separati.
  2. Nel caso non è necessario sottoclasse QThread. Peggio ancora, si sta annullando il metodo run senza alcuna considerazione su ciò che stava facendo.

Questa porzione di codice dovrebbe essere abbastanza

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

Now (Qt versione> = 4.7) per impostazione predefinita QThread avvia un ciclo di eventi nel suo metodo run(). Per correre all'interno di un thread, è sufficiente spostare l'oggetto. Read the doc...

+0

Come posso avviare questo timer all'esterno di somethread (nel thread corrente)? Devo usare QueuedConnection? – jichi

+1

collegare un segnale allo slot del timer 'start()' e attivare il segnale – UmNyobe

+1

Vale a dire 'connettere (somethread, SIGNAL (avviato()), timer, SLOT (start()))' – rbaleksandar

8

Un QTimer funziona solo in un filo che ha un ciclo di eventi.

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

Nelle applicazioni multithread, è possibile utilizzare QTimer in qualsiasi filo che ha un ciclo di eventi. Per avviare un ciclo di eventi da un thread non GUI, utilizzare QThread :: exec(). Qt usa l'affinità del thread del timer per determinare quale thread emetterà il segnale di timeout(). Per questo motivo, è necessario avviare e interrompere il timer nella sua thread; non è possibile avviare un timer da un altro thread.

+0

Ho provato ad aggiungere exec() nel metodo run ma ottengo QEventLoop: non può essere usato senza QApplication. –

+0

Crea QApplication, quindi crea il tuo thread –

10
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(); 
+0

Non mi è chiaro cosa sia 'worker'. – Stormenet

+2

@Stormenet Qualche oggetto con uno slot 'doIt()' che dovrebbe fare il lavoro (nel thread creato) ogni volta che scatta il timer. –

0

È possibile utilizzare il segnale di emettere e avviare il timer all'interno della funzione scanalatura emessa

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

È necessario un ciclo di eventi per disporre di timer.Ecco come ho risolto lo stesso problema con il mio codice:

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

Ecco il pezzo rilevante della documentazione che nessuno degli altri manifesti detto:

int QCoreApplication :: exec()

Immette il ciclo dell'evento principale e attende finché non viene chiamato exit(). Restituisce il valore impostato su exit() (che è 0 se exit() viene chiamato tramite quit()). È necessario chiamare questa funzione per avviare la gestione dell'evento . Il loop eventi principale riceve eventi dal sistema di finestre e li invia ai widget dell'applicazione. Per fare in modo che l'applicazione esegua l'elaborazione inattiva (ad esempio eseguendo una funzione speciale ogni volta che non ci sono eventi in sospeso), utilizzare un QTimer con 0 timeout. È possibile ottenere ulteriori schemi di elaborazione inattiva avanzati utilizzando processEvents().

Problemi correlati