Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 in

    with QObject(parent) in UDP constructor:
    first connect seems not to work
    reconnect works fine, because I get data in

    Here you can find my UDP sender:
    UDP Sender

    Here is a small Test Project with this strange behavior:
    Test Project

    Why I don't get the behavior I expect?


  • Moderators

    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 a nullptr - that is important!), then move to thread. If you need it parented within the thread, you can call setParent() 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?


  • Moderators

    @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.:

    However, I do recommend setting it explicitly - then somebody who will read your code later will be 100% sure what your intention was.

    Ok thats an argument thank you.



  • @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


  • Moderators

    @Wuzi
    question, why do you (want to) disconnect the signals from the socket to you slot?



  • @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.


  • Moderators

    @Wuzi
    youc could also use a bool to check, before emitting the signal

    if(logData)
       emit mySignal();
    


  • @J.Hilk said in Cannot connect signal and slot from different thread.:

    if(logData)
    emit mySignal();

    Yes exactly i do know this and it works fine. Thank you Hilk

    But it would be nice to know why disconnecting does not work.


Log in to reply