What is the correct way to stop QThread?
-
I have used QThread to run a function which takes long long time to complete the execution. Everything works fine but on close of the application (before completion of this threaded function) I am getting segmentation fault.
My questions is what is the correct way to stop the QThread? -
Check QThread documentation: "quit":http://qt-project.org/doc/qt-4.8/qthread.html#quit, "exit":http://qt-project.org/doc/qt-4.8/qthread.html#exit. This wiki article about "threads general usage":http://qt-project.org/wiki/QThreads_general_usage might also give you hints.
-
[quote author="leon.anavi" date="1349979787"]Check QThread documentation: "quit":http://qt-project.org/doc/qt-4.8/qthread.html#quit, "exit":http://qt-project.org/doc/qt-4.8/qthread.html#exit.[/quote]
This will only work if the thread is running its own event loop and if the thread will exit from its run() method immediately after exiting from the event loop. In all other cases you will have to add some kind of "abort" flag (probably a boolean member variable that is "public" or at least has a public setter method). Then you can tell the thread to exit ASAP "from outside" (e.g. from your "main" thread) by setting the abort flag. Of course this will require your thread code to check the abort flag at regular intervals.
Like this:
@void MyThread::run(void)
{
m_abort = false;
while(moreWorkLeft && (!m_abort))
{
doTheNextPieceOfWork();
}
}@In your main thread you'd do something like:
@myThread->m_abort = true; //Tell the thread to abort
myThread->wait(); //Wait until it actually has terminated (waits infinitely)@You may also force a thread to terminate right now via QThread::terminate(), but this is a very bad practice, because it may terminate the thread at an undefined position in its code, which means you may end up with resources never getting freed up and other nasty stuff. So use this only if you really can't get around it...
I'd recommend something like:
@myThread->m_abort = true; //Tell the thread to abort
if(!myThread->wait(5000)) //Wait until it actually has terminated (max. 5 sec)
{
qWarning("Thread deadlock detected, bad things may happen !!!");
myThread->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it!
myThread->wait(); //Note: We have to wait again here!
}@ -
Thanks a lot MuldeR for your response, unfortunately in my case I am not using loops.
Let me put it like this.....
There is a 3rd party function (I don't have source code of that) which takes long long time to complete the execution and I don't want every one to stuck on that function to complete so I kept that function in different thread and emits a signal once that function execution is over. e.g.
@
void MyThread::run(void)
{
3rdParty_fun_of_longer_execution_time(); // function which take long long time to complete
Execution_finished();//Signal to indicate completion of current execution.
}
@Now the problem is : As 3rdParty_fun_of_longer_execution_time() takes longer time and if some one closes the application before it completes execution, system gets crash (Segmentation fault).
I can use terminate but I am not comfortable of doing that as I am not sure what it is doing in side. I wanted some option to stop it gracefully.
-
Other than the terminate() function, there is not much you can do to stop your 3rdParty_fun_of_longer_execution method. That is, unless you can convince the author of said function to make it more well-behaved.
-
In that case, all you can do is: Make sure that your thread will exit from run() as soon as the "3rdParty_fun_of_longer_execution_time()" has returned. Then call QThread::wait() from your main thread and let it wait, no matter how long it takes. Or even better: To avoid that the GUI will freeze, connect a slot to the QThreads "finished()" signal and shutdown your application when that slot is triggered. While waiting for the thread, you may display a message to your users like "Shutting down, please be patient...".
@void MainWindow::closeEvent(QCloseEvent *event)
{
if(m_myThread->isRunning())
{
m_myThread->m_abort = true;
connect(m_myThread, SIGNAL(finished()), this, SLOT(close()), Qt::UniqueConnection);
m_pleaseBePatientBanner->setVisible(true);
e->ignore(); //Prevent to close window this time
}
}@(Either that or: Hide you application and let your application complete the shutdown "silently" in the background)
-
I have a similar situation, but with a function that doesn't execute too long, <1 sec. The problem is that I receive a lot of signals to execute that job, and I use Queued connection to queue them up.
For me both quit() and exit() don't work, only terminate()
And I don't want this message:
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
reimplement QApplication::notify() and catch all exceptions there.