QThread not exiting when signalled using SLOT(quit())
-
@zzaj said:
thread->start(); thread->wait();
You start the thread and then block the main thread to wait for it? This doesn't make much sense, as the main thread will simply infinitely wait for the worker to finish. And if it doesn't, well you have a hanging program.
-
I need to wait as the next step in the main thread is to try and capture an image from the VideoCapture object which will fail unless the connection is opened ie the thread is finished. I realise this kind of defeats the purpose, but using a thread enables me to have a responsive gui.
If you have an alternative solution I would love to hear it. If not, can you answer either of the questions I asked? Why the quit() does not work or how to wait for thread completion OR ~6 seconds
-
Hi and welcome to devnet,
You're blocking your main thread's execution right after starting your thread when calling wait.
Do you want to wait for the connection to happened before calling
capture.isOpened()
? -
@zzaj
When you callwait()
on the thread object, as already noted you're blocking the main thread's event loop. So when you emit thestreamConnector::finished
signal from the worker object, thethread
object is posted an event that thequit
slot should be called. The problem is that without having an event loop running in the main thread this event will not be processed, until the main thread unblocks (i.e. returns fromwait()
). This is because the thread affinity of yourQThread
instance is actually the main thread.If you need to do something and then wait for it (blocking the main thread) I suggest not using threads at all.
Kind regards.
-
Hi, and thanks.
See my reply above (I've also edited the post for clarity). The next step in the main thread is to attempt to get an image so I need this method to return either true or false before continuing. I'm aware that the thread waits on this thread to end, that is the intended functionality. My issue is that it is not closing and hitting the capture.isOpen() despite a successful connection and finished() signal.
-
To add to @kshegunov, if it's something that should be called after your worker object's work is done, then use a slot connected to your finished signal.
-
@kshegunov
Thanks, that makes since. i've done a bit of reading on thread affinity now.But I cannot see an alternative solution here. I need the main program to wait for a connection, and I need it to timeout after a set time or after completion. I also need the main gui to be responsive during this time. None of which I can achieve by running the capture->open(address) method during the main thread.
By using wait(6000) this program operates as I want it to, however it is forced to wait 6 seconds regardless of success or failure. Obviously this is not ideal, i'm looking for the correct way to achieve what I want.
-
@zzaj
See @SGaist's suggestion. You can fiddle a bit with signals and slots, but it should be pretty simple to implement.
You start your thread as you're doing now, but do not callwait()
. Then in the worker object emit a signal to tell your thread that you have a valid connection, and in the slot that is connected to that signal put the rest of your code. It would look something like this:void streamConnector::process() { capture->open(address.toStdString()); // Do some stuff if (capture->isOpened()) emit captureOpened(); emit finished(); }
And you simply subscribe to the
captureOpened()
signal and do whatever you wish with your new and valid connection.Now to handle timeouts, the slot that handles
captureOpened()
can set an internal boolean e.g.bool started
. And you can start a one shot timer (after starting the worker thread) and connect the timer'stimeout()
signal to another slot that checks ifstarted
istrue
orfalse
. This way you'll know whether yourstreamConnector::process()
should be thought as timed-out.