QTimer cannot in QThread
-
QTimer cannot timeout in the QThread.
qDebug() don't print anything
and don't run in to Thread::updateLog().
but QTimer::singleShot() work fine.//thread.h #ifndef THREAD_H #define THREAD_H #include <QThread> #include <QTimer> class Thread : public QThread { Q_OBJECT public: explicit Thread(QObject *parent = 0); protected: void run(); signals: public slots: void updateLog(); private: QTimer *m_timer; }; #endif // THREAD_H
//thread.cpp #include "thread.h" #include <QDebug> Thread::Thread(QObject *parent) : QThread(parent) { m_timer = new QTimer(0); m_timer->setInterval(0); m_timer->moveToThread(this); } void Thread::updateLog() { qDebug()<<"update!"; } void Thread::run() { m_timer->start(1000); //QTimer::singleShot(0, this , &Thread::updateLog); }
//main.cpp #include "widget.h" #include "thread.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); Thread thread; thread.start(); return a.exec(); }
-
Hi,
To add to @m-sue, your thread won't start an event loop either, so even if you slots gets invoked it won't be in the correct thread.
Please take a look at QThread's detailed documentation for the correct usage of this class
-
Hi,
To add to @m-sue, your thread won't start an event loop either, so even if you slots gets invoked it won't be in the correct thread.
Please take a look at QThread's detailed documentation for the correct usage of this class
-
thank you @SGaist @m-sue .
when I add exec() , QTimer work fine.
I am curiosity about why QTimer::singleShot() work fine.@DongMK said in QTimer cannot in QThread:
thank you @SGaist @m-sue .
when I add exec() , QTimer work fine.
I am curiosity about why QTimer::singleShot() work fine.I believe the answer here is because
singleShot()
doesn't use signals/slots. It calls the function you pass directly after the timeout happens. But I am not 100% sure about that so confirm for yourself in the code if you're really curious. :) -
I you create your timer in the "run" method, you do not have to "moveToThread". The timer will be in the thread space. As @SGaist said there is good documentation on using threads. You will see two flavors:
- is the way you did. Derive from QThread and extend it for arbitrary work (not very OO since you are really not creating a new type of thread like a PeriodicThread or SyncedThread).
- QThread as a worker as in the documentation.
Both, are equally valid if you do not care about OOness but I am finding the newer way much easier now that I have played with it more.
And, as always, if you want signal/slot methods to work across your thread bounds, you need to keep the event loop running. Signals are always queued when emitted across thread bounds. So, since your singleShot was done inside the thread boundary, it was NOT queued but the signal acted as a function call.
-
I you create your timer in the "run" method, you do not have to "moveToThread". The timer will be in the thread space. As @SGaist said there is good documentation on using threads. You will see two flavors:
- is the way you did. Derive from QThread and extend it for arbitrary work (not very OO since you are really not creating a new type of thread like a PeriodicThread or SyncedThread).
- QThread as a worker as in the documentation.
Both, are equally valid if you do not care about OOness but I am finding the newer way much easier now that I have played with it more.
And, as always, if you want signal/slot methods to work across your thread bounds, you need to keep the event loop running. Signals are always queued when emitted across thread bounds. So, since your singleShot was done inside the thread boundary, it was NOT queued but the signal acted as a function call.
@Buckwheat @DongMK I think it would be better to create the timer in run(). If you do it in the constructor then you have to move it to the thread as the constructor is not executed in the new thread - new thread starts when you call thread.start(); But in constructor it makes no sence to call moveToThread() as the new thread is not yet started.
It would be even better to allocate the timer on the stack - in this case there is no need to move it to the right thread as it will be moved together with your Thread instance. Why do you allocate the timer on the heap? Why don't you free the timer in destructor? -
@Buckwheat @DongMK I think it would be better to create the timer in run(). If you do it in the constructor then you have to move it to the thread as the constructor is not executed in the new thread - new thread starts when you call thread.start(); But in constructor it makes no sence to call moveToThread() as the new thread is not yet started.
It would be even better to allocate the timer on the stack - in this case there is no need to move it to the right thread as it will be moved together with your Thread instance. Why do you allocate the timer on the heap? Why don't you free the timer in destructor?@jsulm I did say that ... "I [sic] you create your timer in the "run" method..."
Multi-threading can be daunting when it comes to thread-local storage and "other" storage. That is why the newer documentation makes more sense. The object, and all its members, will be moved to the thread and as long as the thread event queue is processed, there are really few limitations.
I suggest you start small and get used to the worker thread concept. You can actually create a nice worker thread base class, say... WTObject to attach all the little signals/slots for started, finished, etc.
-
@Buckwheat @DongMK I think it would be better to create the timer in run(). If you do it in the constructor then you have to move it to the thread as the constructor is not executed in the new thread - new thread starts when you call thread.start(); But in constructor it makes no sence to call moveToThread() as the new thread is not yet started.
It would be even better to allocate the timer on the stack - in this case there is no need to move it to the right thread as it will be moved together with your Thread instance. Why do you allocate the timer on the heap? Why don't you free the timer in destructor? -
@jsulm I did say that ... "I [sic] you create your timer in the "run" method..."
Multi-threading can be daunting when it comes to thread-local storage and "other" storage. That is why the newer documentation makes more sense. The object, and all its members, will be moved to the thread and as long as the thread event queue is processed, there are really few limitations.
I suggest you start small and get used to the worker thread concept. You can actually create a nice worker thread base class, say... WTObject to attach all the little signals/slots for started, finished, etc.
@Buckwheat I'm poor in english and QThread. I can not understand whole your meaning. I will read the QThread's Document and correct my error.