PDA

View Full Version : QTimer in QThread doesn't start or timeout



Boron
30th March 2009, 17:41
Hi there,

I am playing around with QThreads for the first time. And now I have the weird problem that the QTimer in my thread class doesn't start or emit the timeout() signal. Some code:

CanThread::QCanThread( QObject* parent )
: QThread( parent )
{
m_countTimer = new QTimer( this );
m_countTimer->setInterval( 1000 );
connect( m_countTimer, SIGNAL(timeout()), this, SLOT(updateCounter()) );
}

void CanThread::run() {
m_countTimer->start();
exec();
}

void CanThread::stop() {
m_countTimer->stop();
this->quit();
}

void QCanThread::updateCounter() {
m_currentCounter++;
emit showCurrentCounter( m_currentCounter );
} The timer m_countTimer shall timeout all 1000ms. As reaction a counter variable is incremented and the GUI is signalled to display that variable.
(I know it is bullshit to do this that way. A simple timer and the GUI without my CanThread would be enough, but I want get a feeling how deal with threads)

But the slot updateCounter() is never called. Either the timer doesn't start when I call threadObject->start() or the timer doesn't emit its signal timeout().
What is wrong with my code?

talk2amulya
30th March 2009, 17:54
couple of things:

1. QCanThread? just a typo?
2. catch the value returned by connect and see if the signal is connected to slot

rest looks fine

Boron
30th March 2009, 18:03
1. I thought I had removed all 'Q's not to confuse anyone ;).
2. connect() returns "true".

If I add a
QTimer::singleShot(1000, this, SLOT(updateCounter()));
after
m_countTimer->start();
the GUI displays the counter value after a second. But the interval timer still doesn't work. Now I am confused :confused:.

talk2amulya
30th March 2009, 18:19
strange..ok, try checkin the timer ids in constructor and run method..another thing u can try is move all the code from constructor to run method..just for playin around

Boron
30th March 2009, 18:53
The Qt doc tells the timer ID is -1 while timer is not running. So the ID is -1 in my constructor.
After calling start() the ID is a positive number.

When I create and set the interval of the timer in the run() method it works as expected. My GUI is constantly increasing the value.

So there must be a difference in timer objects created in thread constructors and timers created later (e.g. after starting the thread).

talk2amulya
30th March 2009, 19:18
actually thats how threads are supposed to work..whatever code u wanna execute should be in run method..thats when a thread actually kicks off..in every documentation they say, derive from base class and implement run..i believe if u connect in run() and do other initialization in constructor, it should work too..

Boron
30th March 2009, 19:30
No. Timer creation has to be done in run(). If only connect() is done in run() it doesn't work.

talk2amulya
30th March 2009, 19:45
hmm..this whole situation is definitely a bit weird..cuz the documentation should mention that any kind of initialization done in the constructor would not take any effect when the thread is actually run..and although it makes sense that run method should have all the initialization, one can always make a mistake of initializing in constructor being a C++ developer....any guru thoughts on this?

israelins
21st October 2011, 13:08
I don't know if you sove that, but that maybe help others.

Call in class constructor:
this->moveToThread(this);
countTimer->moveToThread(this);

amleto
21st October 2011, 13:51
Added after 4 minutes:


hmm..this whole situation is definitely a bit weird..cuz the documentation should mention that any kind of initialization done in the constructor would not take any effect when the thread is actually run..and although it makes sense that run method should have all the initialization, one can always make a mistake of initializing in constructor being a C++ developer....any guru thoughts on this?

this is because what you code you do in constructor is done in the calling thread. The code in run will be executed in the new thread after start() is called. timers dont work well across thread boundaries so you either need to instantiate the timer in run() or use moveTothread() in run to move the timer.


I don't know if you sove that, but that maybe help others.

Call in class constructor:
this->moveToThread(this);
countTimer->moveToThread(this);

that is ridiculous :-/