Probably the title question is not very explicit. I am using Qt5 on Windows7.
In a thread (QThread) at some point, in the "process()"
function/method, I must wait for the "encrypted()"
SIGNAL belonging to a QSslSocket I am using in this thread. Also I suppose I should use a QTimer and wait for a "timeout()"
SIGNAL in order to avoid getting blocked in an infinite loop...
What I have now is:
// start processing data
void Worker::process()
{
status = 0;
connect(sslSocket, SIGNAL(encrypted()), this, SLOT(encryptionStarted()));
QTimer timer;
connect(&timer, SIGNAL(timeout()), this, SLOT(timerTimeout()));
timer.start(10000);
while(status == 0)
{
QThread::msleep(5);
}
qDebug("Ok, exited loop!");
// other_things here
// .................
// end other_things
emit finished();
}
// slot (for timer)
void Worker::timerTimeout()
{
status = 1;
}
// slot (for SSL socket encryption ready)
void Worker::encryptionStarted()
{
status = 2;
}
Well, obviously it doesn't work. It stays in that while-loop forever...
So, the question is: Is there a way to solve this problem? How can I wait for that "encrypted()"
SIGNAL but not more than - let's say 10 seconds - in order to avoid getting stuck in that waiting-loop/thread?
In asynchronous programming, the "wait for" is considered an anti-pattern. Instead of waiting for things, design the code to react to a condition becoming fulfilled. E.g., connect the code to a signal.
One way of implementing this is to slice your actions into separate states, and do some work when each of the states is entered. Of course if the amount of work is non-trivial, use a separate slot instead of a lambda to keep things readable.
Note the absence of explicit memory management. Use of owning pointers to Qt classes is a premature optimization and should be avoided where unnecessary. The objects can be direct members of the
Worker
(or its PIMPL).The sub-objects must be all a part of the ownership hierarchy that has
Worker
at the root. That way, you can safely move theWorker
instance to another thread, and the objects it uses will follow it. Of course you could also instantiate theWorker
in the correct thread - there's a simple idiom for that. The thread's event dispatcher owns the worker, thus when the thread's event loop quits (i.e. after invokingQThread::quit()
), the worker will be automatically disposed and no resources will leak.The Worker's implementation:
Then:
Note that connecting to
QThread::started()
would be racy: the event dispatcher doesn't exist until some code withinQThread::run()
had a chance to execute. Thus we have to wait for the thread to get there by yielding - this is very likely to get the worker thread to progress far enough within one or two yields. Thus it won't waste much time.I had some time these days and I did some investigation...
Well, I browsed "http://doc.qt.io/qt-5/qsslsocket.html" and found this:
To my real shame, I didn't noticed it before... :(
Definitely need to buy some glasses (unfortunately, it's not a joke!)
I am willing to modify my code accordingly in order to test it (on Monday @ office).
Pretty much chances that it'll work.
Yes, kinda weird to answer my own question, but maybe it IS a solution, so I decided to share :)
You can use a local event loop to wait for the signal to be emitted :
Here it waits until
encrypted
is emitted or the the timeout reaches.