QThread & Lost Queued-Signals
-
Hello everyone,
I have the situation, that somehow signals from a different thread are lost, and I'm unsure why that is the case.
The situation:
I have a classSslSocket
that is only depending onQObject
class SslSocket : public QObject { Q_OBJECT public: SslSocket(QString host, int port, SmtpClient::ConnectionType connection); ~SslSocket(); enum errorType{ connectError, loginError, sendError }; Q_ENUM(errorType) ... ... }
In it, I'm using the asynchronus QSslSocket approch to communicate with a server. Even so I use readyRead and bytesWritten instead of the blocking functions I decided to wrap the class up in a seperated thread.
SslSocket *smtp = new SslSocket("smtp.gmail.com",465,SmtpClient::SslConnection); QThread *t = new QThread(); smtp->moveToThread(t); connect(t, &QThread::started, smtp, &SslSocket::initSslSocket); connect(t, &QThread::finished, smtp, &SslSocket::deleteLater); connect(t, &QThread::finished, t, &QThread::deleteLater); connect(this, &SmtpEmail::destroyed, t, &QThread::quit); connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::errorManagement/*,Qt::DirectConnection*/); //<= Problem ... ... t->start();
It is working as indetend, but while testing for potential Errors, I set the server to refuse the SSL-Handshake.
UsingqDebug
I see that the SIGNALerrorMsg
is emitted, but the SLOTerrorManagement
is not called, ever.But when I change the connection type from
Qt::QueuedConnection
toQt::DirectConnection
, the slot is called! The slot is also called, when I do not movesmtp
to the thread, but let it life in the main thread.Because the object lifes in a different thread I rather would not use DirectConnection if I can avoid it.
So, anyone any idea what is going on ?
Thanks
-
I'm an Idiot.
I overwrote
QWidget::event
to emit a signal in certain situations.bool SmtpEmail::event(QEvent *e) { if(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove ){ QMouseEvent *ev =(QMouseEvent *)e; emit mouseEvent(ev->type(),mapToGlobal(ev->pos())); } return false; }
what I should have written:
bool SmtpEmail::event(QEvent *e) { if(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove ){ QMouseEvent *ev =(QMouseEvent *)e; emit mouseEvent(ev->type(),mapToGlobal(ev->pos())); } return QFrame::event(e); }
returning false als the default value aparently interrupt the QueuedConnection mechanic.
-
@VRonin hi,
I'm quite sure that I'have a event loop and that it is running. I do call QThread::start() , queded-connections inside the threaded class are executed without problem as well. Also QThread::isrunning() returns true:
I added the following to test:
QTimer *timer = new QTimer(); timer->setInterval(500); connect(timer, &QTimer::timeout, timer, [=]{ qDebug() << "Thread"<< QTime::currentTime().toString("ss.zzz"); emit errorMsg(QTime::currentTime().toString("ss.zzz")); }); timer->start();
connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::errorManagement); connect(smtp, &SslSocket::errorMsg, smtp,[=](QString s){qDebug()<< "Queued:"<< s;},Qt::QueuedConnection ); connect(smtp, &SslSocket::errorMsg, smtp,[=](QString s){qDebug()<< "Direct:"<< s;},Qt::DirectConnection ); connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::msg, Qt::QueuedConnection); connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::msg, Qt::DirectConnection); void SmtpEmail::msg(QString s) { qDebug() << "Slot"<< s; }
the result is:
Thread "14.433" Direct: "14.433" Slot "14.433" Queued: "14.433"
The queued connections, except the lambda one, are missing. And I'm not sure you can actually queue lambdas!?
...
I don't think I blocked the main thread.
- I don't use while loops in my main thread. Howerver there is one in the SslSocket class that I use to read the data, but it should not becalled before the readyread signal
if(socket->canReadLine()){ while (socket->canReadLine()) ... }
- I can resize the window without a problem
- I do get information from my other worker thread, that is using a serialport
-
OK, just made a clean project with this code:
QTimer *timer = new QTimer(); QThread *thread = new QThread(); timer->moveToThread(thread); timer->setInterval(500); connect(timer, &QTimer::timeout, this, &MainWindow::mySlot); connect(thread, &QThread::started, timer, QOverload<>::of(&QTimer::start)); thread->start(); void MainWindow::mySlot() { qDebug() << "my Slot"<< QTime::currentTime().toString("mm.zzz"); }
It is calling the slot, like it should. If I copy and paste that one to my class where I have the problems, and adjust mySlot,
the slot is not called....
I'll have to look into it more. I defenitly messed up somewhere...
-
I'm an Idiot.
I overwrote
QWidget::event
to emit a signal in certain situations.bool SmtpEmail::event(QEvent *e) { if(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove ){ QMouseEvent *ev =(QMouseEvent *)e; emit mouseEvent(ev->type(),mapToGlobal(ev->pos())); } return false; }
what I should have written:
bool SmtpEmail::event(QEvent *e) { if(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove ){ QMouseEvent *ev =(QMouseEvent *)e; emit mouseEvent(ev->type(),mapToGlobal(ev->pos())); } return QFrame::event(e); }
returning false als the default value aparently interrupt the QueuedConnection mechanic.