Cannot connect signal and slot from different thread.
-
Hello,
I'm trying to create an udp socket in a different thread. After I created the socket, I try to connect QUdpSocket::readyRead with my own function readData() from another thread. When I initialize in the UDP constructor QObject with the default constructor with no arguments, the output result is, that the first connect works fine and I get data, the disconnect works fine, because I don't get anymore data, but the reconnect does not work anymore.
When I initialize in the UDP constructor QObject with MainWindow as parent(QObject(parent)), then the first connect does not work, but the reconnect works fine, and I get data in.Why the different initialisation of QObject changes the behavior?
Why not every connect is successful and I don't get data everytime?[0_1537179976696_UDPClient.zip](Uploading 100%)Second test I made was to disable QThread:
// m_udp->moveToThread(&m_udp_thread); // m_udp_thread.start();
with QObject() in UDP constructor:
first connect works fine.
disconnect works fine.
reconnect does not work, because I don't get anymore data inwith QObject(parent) in UDP constructor:
first connect seems not to work
reconnect works fine, because I get data inHere you can find my UDP sender:
UDP SenderHere is a small Test Project with this strange behavior:
Test ProjectWhy I don't get the behavior I expect?
-
Please take a look at the docs:
The object cannot be moved if it has a parent
https://doc.qt.io/qt-5/qobject.html#moveToThread
So, create your QUdpSocket without parent (not
QObject()
but anullptr
- that is important!), then move to thread. If you need it parented within the thread, you can callsetParent()
later.Also, remember to use Qt::QueuedConnection for your inter-thread connections - then you don't have to worry about locking any mutexes and such.
-
@sierdzio said in Cannot connect signal and slot from different thread.:
Also, remember to use Qt::QueuedConnection for your inter-thread connections - then you don't have to worry about locking any mutexes and such.
Thank you sierdzio for your help! Qt::QueuedConnection will be made automatically when I create a connection between two threads or do I have to set it explizit?
I tried to init QObject(nullptr) in UDP, but it does not change anything. I don't understand why it will not work, when I remove the moveToThread function to use just one thread?
-
@Wuzi said in Cannot connect signal and slot from different thread.:
Qt::QueuedConnection will be made automatically when I create a connection between two threads or do I have to set it explizit?
It is done automatically if you connect after moving to thread. That's another important thing: connect signals and slots after you move to thread!
However, I do recommend setting it explicitly - then somebody who will read your code later will be 100% sure what your intention was.
-
-
@sierdzio said in Cannot connect signal and slot from different thread.:
That's another important thing: connect signals and slots after you move to thread!
Yes I do this :
mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { m_mutex = new QMutex; m_udp = new UDP(this, m_mutex); m_udp->init(); m_udp->moveToThread(&m_udp_thread); m_udp_thread.start(); qDebug() << "Connect"; m_udp->connectDataReady(); sleep(5); qDebug() << "Disconnect"; m_udp->disconnectDataReady(); sleep(5); qDebug() << "Reconnect"; m_udp->connectDataReady(); }
UDP.cpp:
void UDP::connectDataReady(){ qDebug() << connect(m_socket, &QUdpSocket::readyRead, this, &UDP::readData, Qt::ConnectionType::QueuedConnection); } void UDP::disconnectDataReady(){ disconnect(m_socket, &QUdpSocket::readyRead, this, &UDP::readData); }
I tried also to remove the direction connection
m_udp->disconnectDataReady();
by using a queued connection, but it doesn't change something
-
@J.Hilk said in Cannot connect signal and slot from different thread.:
to you slot?
because I would like to stop logging data. You bring me to another idea I can try: this is only a part of my project udpLogger. When the readyRead signal is emitted, the UDP object reads the data in and emits a signal which signals the Plots object, that new data is available and the Plots object processes the new data. Now instead of disconnecting to readyRead, I can disconnect to the Plots object.