PDA

View Full Version : QThread : how to stop an infinite loop



TarielVincent
24th February 2012, 13:02
I execute in a Qthread an image processing procedure taking around 3 hours without the possibility to put some check points inside it for a exit gate. The problem is I cannot stop it. This code represents this problem :


class Toto : public QObject
{
Q_OBJECT
public slots:
void exec(){
//I represent the real process with an infinite loop
while(1==1);
}
};
int main(int argc, char *argv[])
{
QApplication aa(argc, argv);
QThread * t1 = new QThread;
Toto * toto1 = new Toto;
QThread * t2 = new QThread;
Toto * toto2 = new Toto;
QPushButton push;
push.show();
toto1->moveToThread(t1);
toto2->moveToThread(t2);
QMetaObject::invokeMethod(toto1, "exec", Qt::QueuedConnection);
QMetaObject::invokeMethod(toto2, "exec", Qt::QueuedConnection);
QApplication::connect(&push, SIGNAL(pressed()), t1,SLOT(terminate()), Qt::QueuedConnection);
QApplication::connect(&push, SIGNAL(pressed ()), t2,SLOT(terminate()), Qt::QueuedConnection);
t2->start();
t1->start();
return aa.exec();
}

The problem is my infinite loop is not interrupted when I press the buttom.
Do you have any idea to solve this problem?
Thanks,
Vincent

qlands
24th February 2012, 13:15
Hi,

Maybe the way you are using QThread is not the correct.

I had the same problem once and this is how I made it, maybe is not the cleanest way:

Maybe your code in the thread goes through a big loop of process. I would put those process in the run() of a QThread (subclasing QThread). In that code you can put a variable called stopnow. That if its true the loop will break. Then you can set that variable to true out of the thread with a slot called stopIt(). !!Use a mutex before changing its value. And thats it... If you call stopit, it will stop.

Carlos.

TarielVincent
24th February 2012, 13:27
Thanks Carlos for your reactivity ;)
However, my infinite loop represents more than two hundreds algorithms of my image processing library. I cannot add a break point for each one. In other multi-threading library, we can kill a thread as a "pirate" without a flag.
So...

qlands
24th February 2012, 13:32
ok. So maybe is that such code is not in run() then stop() does not work. Try by subclassing QThread and put that code in run(). Then start the thread with start(). Those many pointers and metaobjects invokes are really don't needed.



class MyThread : public QThread
{
public:
void run();
};

void MyThread::run()
{
//My massive process here
}


Carlos

TarielVincent
24th February 2012, 13:55
Thanks

Maybe your code in the thread goes through a big loop of process. I would put those process in the run() of a QThread (subclasing QThread). In that code you can put a variable called stopnow. That if its true the loop will break. Then you can set that variable to true out of the thread with a slot called stopIt(). !!Use a mutex before changing its value. And thats it... If you call stopit, it will stop.
Thanks Carlos but as I said, the infinite loop was just a representation of my image processing algorithms. I cannot changed all algorithms for that...

Spitfire
24th February 2012, 14:38
However even if the infinite loop (the massive process) is in the run, you cannot call the slot terminate() signal because you do not call the thread's event loop.Actually, that's not entirely true.

From documentation:

void QThread::terminate () [slot]
Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to cleanup after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.


You're not mentioning what system you're using, on windows your example works exacly as you expect it to work, thread is terminated as soon as the button is pressed.
If you're using linux then it may not be the case, doc mention this as well:

void QThread::terminate () [slot]
Terminates the execution of the thread. The thread may or may not be terminated immediately, depending on the operating systems scheduling policies. Use QThread::wait() after terminate() for synchronous termination.

TarielVincent
24th February 2012, 14:55
Thanks Spitfire
Actually, I was aware of this fact The thread can be terminated at any point in its code path. It is why I implement my algorithms like that. But I didn't have the expected result.
I am in linux.

Spitfire
24th February 2012, 15:41
I'm not an expert in linux so I'm not sure how you can deal with it.
What I can suggest if there's no other options is to make the image processing library a commandline tool and launch it in a QProcess rather than QThread.
This way you will be able to kill it by deleting the process or calling system kill command.

Added after 23 minutes:

Or try using pthread_kill() (http://linux.die.net/man/3/pthread_kill) or something similar.

TarielVincent
24th February 2012, 16:03
My image processing library is included in Graphical User Interface. With my colleague, we choose this solution. if after n-seconds,the thread is still running. We display a pop-up to inform that a thread cannot stop and a restart is required with Qprocess little bit as your solution.
Thanks

MarekR22
24th February 2012, 21:22
Hi if you are doing some image processing then using QThread is not recommended.
Anyway if you insist on QThread usage you shouldn't subclass QThread at all. See this article (http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/) where author of QThread class explains how it should be done and way most people are sub-classing (history reason).

Anyway the best thing to use is Qt Cuncurent (http://developer.qt.nokia.com/doc/qt-4.8/threads-qtconcurrent.html) framework. If you have task which can be split to pieces the you application will scale autocratically depending on number of cores available.