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

can't sending data outside qtcpsocket thread



  • Hi,
    anyone can help me about qtcpsocket with qthread after this .

    i want to send message over qtcpsocket, but i don't know why i got error in Application logs

    error : QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

    here is the readyRead() function :

    void UpdataServerThread::readyRead()
    {
        qDebug()<<updata_socket;
        qDebug()<<"connected_client_socket => "<<connected_client_socket;
        qDebug()<<"connected_client_ip => "<<connected_client_ip;
    
        QByteArray Data = updata_socket->readLine();
        QJsonDocument document = QJsonDocument::fromJson(Data.data());
        QJsonObject object = document.object();
    
        //qDebug()<<"current thread :"<<QThread::currentThread()<<" DEVICE::"<<updata_socket->peerAddress()<<"in : "<<Data.data();
    
        //authorize device
        if(Data.contains("devNumber")){
            connected_client_ip.insert(updata_socket->peerAddress(),object.value("devNumber").toString());
            QString str = "{\"msg\":\"Device registered successfully.\",\"timestamp\":"+QString::number(QDateTime::currentSecsSinceEpoch())+"}";
            QByteArray registered_device = str.toUtf8();
    
            ((QTcpSocket*)connected_client_socket.value(updata_socket->peerAddress()))->write(registered_device);
    
        }
        qDebug()<<"connected_client_ip::"<<connected_client_ip;
    }
    

    I've read topic similar topic like this, I haven't got solution.

    in this example of threadedfortuneserver , i saw write() in run() function is work as well as my code in run() function to ,

    how do I use write() outside run() function ?

    here is my code



  • @rifky said in QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread:

    solve with

    connect(updata_socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
    
    

    error : QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

    here is the readyRead() function :

    void UpdataServerThread::readyRead()
    {
        qDebug()<<updata_socket;
        qDebug()<<"connected_client_socket => "<<connected_client_socket;
        qDebug()<<"connected_client_ip => "<<connected_client_ip;
    
        QByteArray Data = updata_socket->readLine();
        QJsonDocument document = QJsonDocument::fromJson(Data.data());
        QJsonObject object = document.object();
    
        //qDebug()<<"current thread :"<<QThread::currentThread()<<" DEVICE::"<<updata_socket->peerAddress()<<"in : "<<Data.data();
    
        //authorize device
        if(Data.contains("devNumber")){
            connected_client_ip.insert(updata_socket->peerAddress(),object.value("devNumber").toString());
            QString str = "{\"msg\":\"Device registered successfully.\",\"timestamp\":"+QString::number(QDateTime::currentSecsSinceEpoch())+"}";
            QByteArray registered_device = str.toUtf8();
    
            ((QTcpSocket*)connected_client_socket.value(updata_socket->peerAddress()))->write(registered_device);
    
        }
        qDebug()<<"connected_client_ip::"<<connected_client_ip;
    }
    

    but i want to write outside ,

    void UpdataServerThread::sendCommand(QByteArray cmd)
    {
        qDebug()<<"current thread :@sendCommand"<<QThread::currentThread();
    
        //    qDebug()<<"connected_client_ip::"<<connected_client_ip;
        qDebug()<<"UpdataServerThread::sendCommand::"<<cmd;
        updata_socket->write("hi22");
    }
    

    how can i fix this code?



  • @rifky said in can't sending data outside qtcpsocket thread:

    how can i fix this code?

    Perhaps you could use QTimer::singleShot():

    void UpdataServerThread::sendCommand(QByteArray cmd)
    {
        qDebug()<<"current thread :@sendCommand"<<QThread::currentThread();
    
        //    qDebug()<<"connected_client_ip::"<<connected_client_ip;
        qDebug()<<"UpdataServerThread::sendCommand::"<<cmd;
        if(QThread::currentThread() != updata_socket->thread())
           QTimer::singleShot(0, updata_socket, [updata_socket](){
                   updata_socket->write("hi22");
               });
        else
            updata_socket->write("hi22");
    }
    


  • @KroMignon said in can't sending data outside qtcpsocket thread:

    Perhaps you could use QTimer::singleShot():

    void UpdataServerThread::sendCommand(QByteArray cmd)
    {
        qDebug()<<"current thread :@sendCommand"<<QThread::currentThread();
    
        //    qDebug()<<"connected_client_ip::"<<connected_client_ip;
        qDebug()<<"UpdataServerThread::sendCommand::"<<cmd;
        if(QThread::currentThread() != updata_socket->thread())
           QTimer::singleShot(0, updata_socket, [updata_socket](){
                   updata_socket->write("hi22");
               });
        else
            updata_socket->write("hi22");
    }
    

    thx for response but i got error :

    updataserverthread.cpp:79:50: error: 'updata_socket' in capture list does not name a variable
    updataserverthread.cpp:79:66: error: expected body of lambda expression

    ../qtcpsocket_w_qthread/updataserverthread.cpp:79:50: error: 'updata_socket' in capture list does not name a variable
                QTimer::singleShot(0, updata_socket,[updata_socket]()){
                                                     ^
    ../qtcpsocket_w_qthread/updataserverthread.cpp:79:66: error: expected body of lambda expression
                QTimer::singleShot(0, updata_socket,[updata_socket]()){
                                                                     ^
    2 errors generated.
    


  • @rifky said in can't sending data outside qtcpsocket thread:

    QTimer::singleShot(0, updata_socket,[updata_socket]()){

    You have one extra closing parenthesis!
    ==> should be QTimer::singleShot(0, updata_socket,[updata_socket]() {



  • @KroMignon said in can't sending data outside qtcpsocket thread:

    QTimer::singleShot(0, updata_socket,updata_socket {

        qDebug()<<"UpdataServerThread::sendCommand::"<<cmd;
        if(QThread::currentThread() != updata_socket->thread()){
            QTimer::singleShot(0, updata_socket,[updata_socket]() {
                updata_socket->write("hi22");
            });
        }else{
            updata_socket->write("hi22");
        }
    

    is it correct ?

    i still got error
    updataserverthread.cpp:79:46: error: 'updata_socket' in capture list does not name a variable
    Screen Shot 2020-08-14 at 18.38.08.png



  • @rifky said in can't sending data outside qtcpsocket thread:

    is it correct ?

    Why this question? Does it work or not?
    If you are not confident with lambda functions take a look at this ==> https://medium.com/genymobile/how-c-lambda-expressions-can-improve-your-qt-code-8cd524f4ed9f



  • thx for help sir @KroMignon
    i change to

     QTimer::singleShot(0, updata_socket,[this]() {
    

    it's working



  • @rifky said in can't sending data outside qtcpsocket thread:

    i change to
    QTimer::singleShot(0, updata_socket,this {

    it's working

    Sorry my fault, I did not notice that updata_socket is not a local variable but a member of your class.
    But this will not resolve your threading issue, I think you should change this to:

    void UpdataServerThread::sendCommand(QByteArray cmd)
    {
        qDebug()<<"current thread :@sendCommand"<<QThread::currentThread();
    
        //    qDebug()<<"connected_client_ip::"<<connected_client_ip;
        qDebug()<<"UpdataServerThread::sendCommand::"<<cmd;
        if(QThread::currentThread() != updata_socket->thread())
        {
           auto localVariable = updata_socket
           QTimer::singleShot(0, localVariable, [localVariable](){
                   localVariable->write("hi22");
               });
        }
        else
            updata_socket->write("hi22");
    }
    


  • @KroMignon no problem, thx for helping me, I really appreciate it


Log in to reply