PDA

View Full Version : How to make a QThread run continuously?



N3wb
17th April 2010, 03:41
I need to have a thread running separate from the main application thread; it's going to watch a serial port and emit a signal when new data arrives, and the main window picks up the signal and stores the new data. How can I make a thread that keeps running forever? Here's my relevant code:



// in the main window's file
Thread *myThread = new Thread();
connect(myThread, SIGNAL(testSignal(QString)), this, SLOT(testSlot(QString)));


// in the .h file
class Thread : public QThread
{
Q_OBJECT

public:
Thread();
signals:
void testSignal(QString message);
protected:
void run();
private:
};

// in the .cpp file
void Thread::run()
{
while(1)
{
emit(testSignal("hello world!"));
}
}

Thread::Thread()
{
run();
}


When I try to run the application, my CPU usage goes up to about 100% - I assume because the thread is running without any sort of "wait" programmed in. So I tried adding the "sleep(seconds)" function inside the while loop, but for some reason this stalls the whole application, not just the thread.

Any idea what I should do?

Thanks!

Lesiok
17th April 2010, 09:18
First : don't call run() in constructor.
Second : read once more detailed description of QThread (http://doc.trolltech.com/4.6/qthread.html#details).

With this construction of Thread::run You are blocking event loop.

N3wb
17th April 2010, 16:10
Thanks for linking to the documentation! I had been reading the 3.3 documentation by accident, which wasn't nearly as informative..

So, if I understand correctly, the event loop is supposed to be inside of "exec()," correct? Would this be a legitimate way of implementing what I want to do?



// inside main window file
Thread *myThread = new Thread();
connect(myThread, SIGNAL(testSignal(QString)), this, SLOT(testSlot(QString)));
myThread->start();



// inside thread's .h file
class Thread : public QThread
{
Q_OBJECT

public:
Thread();
signals:
void testSignal(QString message);
protected:
void run();
int exec();
private:
};



// inside thread's .cpp file
void Thread::run()
{
exec();
}

Thread::Thread()
{
}

int Thread::exec()
{
while(1)
{
emit(testSignal("hello world!"));
sleep(1);
}
}



Why is there difference between having the loop in the "run()" or "exec()" functions, though? It's the same code in both functions, but for some reason only works in the "exec()" function?

Thanks!

Talei
18th April 2010, 01:47
Here is how thread work's (AFAIK, please correct me if I'm wrong), using Your example:

Thread *myThread = new Thread();
call a constructor:

Thread::Thread()
{
}
Then thread is on the stack, so you can fire it up like so:

myThread->start();
and in the thread this protected run() is always called, as manual said "starting point for the thread":

void Thread::run()
{
exec();
}
Here You want to start exec()ution of the thread. Calling exec() tell thread to enter event loop. Thread run until exit()/quit() is called, so In Your case forever. Exec() is int because it is similar to main function "int main()" in normal program, it returns int at the end of execution to let you know if there was error int != 0.

int Thread::exec()
{
while(1)
{
emit(testSignal("hello world!"));
sleep(1);
}
}
Your thread runs forever, because no exit() or quit() is called, and the signal is emitted each 1s.
So to sum it up, run() is called after mythread->start(), and exec() enters event loop for the thread.
You could do something like this also:

void Thread::run()
{
myfirstfunction();
mysecoundfunction();
exec();
}
void Thread:: myfirstfunction()
{
//do some heavy duty stuff / blocking gui operation
}
void Thread:: mysecoundfunction()
{
//proces data
exit();
}

And, depending on what is in myfirs/secound function, the execution flow is first then secound and end of the thread. Also note that if You don't call exit() / quit() inside thread, thread runs "forever" (actually main app don't know if thread execution ended or not ), and using delete mythread() yields error "QThread: Destroyed while thread is still running" or similar. Depending what you are doing in the thread, or on what point You call delete application crash or simply runs but only output error. Also always delete after new because this is mem leek, and depending on Your implementation or data inside thread you can run out of the memory.
I hope this helps to understand how thread works, and again this information is as I see the thread, maybe there is some mistake so please point them out.
Best regards.

Lesiok
18th April 2010, 12:16
Why is there difference between having the loop in the "run()" or "exec()" functions, though? It's the same code in both functions, but for some reason only works in the "exec()" function?

Thanks!
There is nothing difference. Here is code of original QThread::exec method :

int QThread::exec()
{
Q_D(QThread);
QMutexLocker locker(&d->mutex);
d->data->quitNow = false;
QEventLoop eventLoop;
locker.unlock();
int returnCode = eventLoop.exec();
return returnCode;
}

As You see You never create and exec event loop. Yours Thread class must be defined something like that :


class Thread : public QThread
{
Q_OBJECT

public:
Thread();
signals:
void testSignal(QString message);
slots:
void mTimeOut();
protected:
void run();
};

Thread::Thread()
{
}

void Thread::run()
{
QTimer::singleShot(0, this, SLOT(mTimeOut()));

exec();
}

void Thread::mTimeOut()
{
//do what You need in one step
emit(testSignal("hello world!"));
//do sleep and after start next step
QTimer::singleShot(1, this, SLOT(mTimeOut()));
}