#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"); } }
}
-
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 inMyThread::run
so it most likely gets executed in main thread (the thread in which MyThread object was created), and not your thread (the thread insiderun()
). You can check ifthis->thread()
is the same inrun()
and insendQuestions()
to be sure.I strongly suggest using the worker thread pattern - see QThread documentation.
-
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.