#QTHREAD



  • Hi everyone, i have a game mulitithread application, a server and many clients.
    In Server Program, i creat 2 class. First class- mythread, and other -my server.
    In mythread class, i have some functions, and slots to receive, send and bla. In my server class, i have a mythread list to append any creatated thread. Now, i want to send data from myserver to client; some things like this:
    for(int i = 0; i < m_threadList.size(); i++)
    {
    m_threadList.at(i)->sendToClient(m_threadList.at(i)->getClients().at(i),"hello");
    }

    and i have receive this error:
    @
    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x28799d30. Receiver '' (of type 'QNativeSocketEngine') was created in thread 0x0x3e791be0", file kernel\qcoreapplication.cpp, line 577
    @

    how do i fix this ? please help me!
    sorry for my english!

    //your code here
    //here is myThread.h
    
    class MyThread : public QThread
    {
        Q_OBJECT
    public:
        explicit MyThread(qintptr ID, QObject *parent = nullptr);
    
        void run();
    
    signals:
        void error(QTcpSocket::SocketError socketerror);
        void checkOK();
    public:
        QList<QTcpSocket *> getClients(); //  returnn socket  list
    public slots:
       void readyRead();
       void disconnected();
       void sendQuestions(); // send questions
       qint64 sendToClient(QTcpSocket *socket, const QString &str);
    
    private:
        qintptr socketDescriptor;
        QList<QTcpSocket*> connections;  
        QTcpSocket *socket;
    

    and here is mythread.cpp

    //your code here
    MyThread::MyThread(qintptr ID, QObject *parent) :
        QThread(parent)
    {
        this->socketDescriptor = ID;
    }
    
    void MyThread::run()
    {
        qDebug() << "thread run :" << QThread ::currentThread();
        // thread starts here
        qDebug() << " Thread started";
        socket = new QTcpSocket();
    
        // set the ID
        if(!socket->setSocketDescriptor(this->socketDescriptor))
        {
            // something's wrong, we just emit a signal
            emit error(socket->error());
            return;
        }
        else
        {
        connections.append(socket);
        }
      //  m_demo = connections;
    
        // connect socket and signal
        connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
        connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    
        qDebug() << socketDescriptor << " Client connected";
        exec();
    
    }
    
    void MyThread::disconnected()
    {
        qDebug() << socketDescriptor << " Disconnected";
        socket->deleteLater();
        exit(0);
    
    }
    
    void MyThread ::readyRead()
    {
    
        QByteArray arrBlock = socket->readAll();
        QDataStream out(&arrBlock, QIODevice::ReadOnly);
        QString rec;
    
        out >> rec;
        qDebug() << rec;
    
    }
    
    QList<QTcpSocket *> MyThread::getClients()
    {
        qDebug() << "clients thread :" << QThread ::currentThread();
        return connections;
    }
    
    void MyThread :: sendQuestions()
    {
        int temp = 0;
        // doc file cau hoi
        QTextStream out(stdout);
        QFile file("E:/Visual/ANLab/Client-Server(Game)/server/question.txt");
         if (!file.open(QIODevice::ReadOnly)) {
           qWarning("Cannot open file for reading");
           return ;
         }
       //  QTextStream in(&file);
         QTextStream m_in(&file);
         while (!m_in.atEnd())
         {
             int i =0 ;
             temp++;
             QString line = m_in.readLine();
    
             // gui den tat ca cac client cac cau hoi
            for( i = 0;i < connections.size() ; i++)
            {
                sendToClient( connections.at(i), (qPrintable(line)) );// chuyen doi kieu QString ve const char
             }
           }
          file.close();
    }
    
    qint64 MyThread::sendToClient(QTcpSocket *socket, const QString &str)
    {
        QByteArray arrBlock;
        QDataStream out(&arrBlock, QIODevice::WriteOnly);
        out << quint16(0) << str;
    
        out.device()->seek(0);
        out << quint16(arrBlock.size() - sizeof(quint16));
    
        return socket->write(arrBlock);
    }
    
    

    here is my server.h

    //your code here
    #ifndef MYSERVER_H
    #define MYSERVER_H
    
    
    #include <QTcpServer>
    #include "mythread.h"
    
    class MyServer : public QTcpServer
    {
        Q_OBJECT
    public:
        explicit MyServer(QObject *parent = nullptr);
        void startServer();
    
    
    signals:
        void checkOK();
    
    public slots:
        void incomingConnection(qintptr socketDescriptor);
        //-----------BO SUNG---------------//
        void update();
    
    
    
    private:
      int m_person = 3 ; // so luong nguoi choi toi da doc tu file config
      int count = 0; // dem so nguoi choi thuc tai
      int flag = 1; // bien co danh dau de ket thuc su gui dem thoi gian nguoc
      int m_time = 1;
      QTime time; //  lay thoi gian troi qua
      QTimer *timer;// thuc hien interval gui thoi gian dem nguoc ve cho nguoi dung sau moi 5s
      QList <MyThread*> m_threadList;
    
    };
    
    #endif // MYSERVER_H
    
    and the last myserver.cpp file
    

    //your code here
    #include "myserver.h"
    #include "mythread.h"

    MyServer::MyServer (QObject *parent) :
    QTcpServer(parent)
    {

    }

    void MyServer::startServer()
    {
    qDebug() << "startServer :" << QThread::currentThreadId();
    int port = 6547;

    if(!this->listen(QHostAddress::Any,port))
    {
        qDebug() << "Could not start server";
    }
    else
    {
        qDebug() << "Listening to port " << port << "...";
    }
    

    // send time clients
    time.start();
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()),this, SLOT(update()));
    timer->start(5000);

    }

    void MyServer::incomingConnection(qintptr socketDescriptor)
    {
    count += 1;
    // We have a new connection
    qDebug() << socketDescriptor << " Connecting...";

    MyThread *thread = new MyThread(socketDescriptor, this);
    connect( thread, SIGNAL(finished()),thread, SLOT(deleteLater()) );
    connect( this,  SIGNAL(checkOK()),thread, SLOT(sendQuestions()), Qt::DirectConnection );
    
    if(count > m_person)
    {
    
        thread->deleteLater();
    }
    
    else
    {
        m_threadList.append(thread);
        thread->start();
    }
    

    }

    void MyServer :: update()
    {

    if(  time.elapsed() > m_time*60000 || count == m_person )
    {
        flag = 0;
        timer->stop();
        emit checkOK();
    
    }
    
    qDebug() << "thread update:" << QThread::currentThreadId();
        if(  flag == 1 )
        {
            for(int i = 0; i < m_threadList.size(); i++)
            {
               QByteArray tmp_m = QByteArray::number(m_time * 60 - time.elapsed() / 1000);
    
    
             // error here
               m_threadList.at(i)->sendToClient(m_threadList.at(i)->getClients().at(i),"hello");
             
            }
    
     }
    

    }


  • Moderators

    I don't have time to analyse your whole code, but I think the bad bit can be in MyThread :: sendQuestions(). That method is not executed in MyThread::run so it most likely gets executed in main thread (the thread in which MyThread object was created), and not your thread (the thread inside run()). You can check if this->thread() is the same in run() and in sendQuestions() to be sure.

    I strongly suggest using the worker thread pattern - see QThread documentation.


  • Qt Champions 2018

    @nam_anlab

    or just to add to @sierdzio: avoid threads.

    For your simple example they are most likely not needed.

    A server can handle dozens of clients in a single thread, if it works asynchronous, like Qt servers do.



  • @sierdzio i think so, thank you so much !


 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.