[SOLVED]Quitting a Qthread with blocking while(1)
-
Hello,
I am facing problems in quitting a object running in a thread.
Below is the forever while loop which runs in Qthread.
@while (1) {
......
int TimeOut = -1; // Infinite Timeout
int PollReturn = poll(fdset, m_NumbOfFileDesc, TimeOut);
if (PollReturn < 0) {
qDebug("\n poll() failed!\n");
return;
}if (PollReturn == 0) { qDebug("."); } //Emit signals etc...... }@
The blocking "poll" is preventing the quitting of thread. Is there an solution for this problem ?.
The below message can be seen in console "QThread: Destroyed while thread is still running"Thanks!
Nikhil -
Hello,
Don't do a while(1), rather use an exit variable something like:
@
while (_continue){
// processing
}
@and have somewhere else the code to set _continue to 0 (I'd use a QAtomicInt for that)
Don't forget to allow some time for the thread to finish, using wait for example. -
Hello SGaist, Thanks for your reply. I want an Blocked while loop. Don't want to loop unless the monitored file has changed, i.e poll system call comes out of block. I am monitoring a GPIO which is connected to a softswitch.
-
Further, yeah i do use Thread->quit() and then Thread->wait(TimoutValue);
-
quit() will only work if you have an QEventLoop, which is not your case since you are in an infinite loop, hence the suggestion of using an exit variable that stays at 1 as long as you don't tell it otherwise and i.e a stop function
@
void MyClass::stop()
{
_continue = 0;
wait(30000);
}
@ -
Ok, So what i understand is that i cant have a blocked system call in a while loop , especially in a QObject which is moved to a Qthread ?
-
Never said that, from the code and what you told, you have a forever loop running in a QThread. I assume it's in the run re-emplementation.
Now you're telling that the while loop is in a QObject ? Then, you will have to show more code, without that it's getting unclear.
In the case of the run re-emplementation, how do you expect the thread to end gracefully since you're in a forever loop ? Quit is suited for a QThread starting it's event loop.
The poll call will at a point in time return something, then the loop with run again, that's why the exit variable is used, once it's set to 0, next time poll returns, it will get out of the loop and end things gracefully.
I hope my idea is clearer
-
I dont inherit Qthread for my object. Instead i move my object to QThread.
"Referred to the link":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/Below is the code snippet-
@ mp_PollingThread = new QThread(); // QThread
mp_GpioPoller = new GpioPoller(m_SoftSwitchManager.GetSoftSwitchFd()); // QObject
mp_GpioPoller->moveToThread(mp_PollingThread); // Now QObject is on its own thread.--
CONNECTSIGNALSLOT(mp_GpioPoller, OnSoftSwitchPressed(), &m_SoftSwitchManager, OnSoftSwitchPressed());
connect(mp_PollingThread, SIGNAL(started()), mp_GpioPoller, SLOT(Run()));@ -
Ok, then may i offer an alternative ?
@
class Poller : public QObject
{
Q_OBJECTpublic:
explicit Poller(QObject *parent = 0);public slots:
void startPolling();
void stopPolling();private slots:
void doPolling();private:
bool _continue;Q_DISABLE_COPY(Poller)
}
Poller::Poller(QObject *parent):
QObject(parent),
_continue(false)
{
}void Poller::startPolling()
{
if (_continue) {
return;
}_continue = true; doPolling();
}
void Poller::stopPolling()
{
_continue = false;
}void Poller::doPolling()
{
// Do your polling stuffif (_continue) {
QTimer::singleShot(0, this, SLOT(doPolling()));
}
}
@Just an idea, but so you don't need a forever loop and the polling goes as fast as it can and you can also adjust the speed if it happens too many time.
Hope it helps
-
Hello, appreciate your efforts for providing an alternative idea.
I just want a confirmation from you that when you say poll , did you mean"linux system call poll ?":http://linux.die.net/man/2/poll
-
Indeed, i updated the code so it'll be less confusing
-
Ok Thanks!, I will give a try on the target and check if the performance gets degraded because of timer timeouts happening at every 0 seconds.
Right now poll is a blocked call , but what i understand from your code snippet is that i should make it an unblocked call ,else doPolling() wont get completed and the event loop will be stuck. -
Unless you don't timeout on poll, it'll block only for a certain amount of time, so will the event loop from your thread, nothing wrong with that, it won't freeze your gui thread. And that's basically why you created a secondary thread, no ?
-
We have gui as a separate process, and a main process which does the backend job of processing . But , still we have several other threads running in the main process and i dont want a simple gpio monitoring thread to poll every time, hence was using a a blocking call so that gpio monitoring was literally paused and only active when gpio state changed.
But it looks like have to stick to your solution for now .
-
That's what will happen then. As long as your poll is blocking, the timer won't be fired. Then once it polled something, your processing will be done then it will restart polling again immediately
-
Yeah , you are right .Thanks for the solution. I will mark the topic as solved.