Qt “There is no suitable function to call to connect”, Qt Fortune Threaded Server example change

I am trying to modify the Qt Fortune Threaded Server example to read text from a connection, and then repeat it. I defined tcpSocket in FortuneThread.h as follows:

QTcpSocket tcpSocket; 

My new start function for the stream is as follows:

 void FortuneThread::run() { if (!tcpSocket.setSocketDescriptor(socketDescriptor)) { emit error(tcpSocket.error()); return; } connect(&tcpSocket, SIGNAL(readyREAD()), this, SLOT(readCommand()) ); } 

Which compiles and runs, but as soon as I connect, I get this error (referring to the connection string):

 QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x1eeb920), parent thread is QThread(0x1bb3f90), current thread is FortuneThread(0x1eeb8f0) QObject::connect: No such signal QTcpSocket::readyREAD() in ../fortune/fortunethread.cpp:60 

Can someone explain the reason to me? Since tcpSocket is defined inside the FortuneThread class (which runs as a separate thread) and "this" refers to FortuneThread, I assume that both objects are inside the thread? How to fix it?

0
multithreading qt qthread
source share
3 answers

Your socket object was created in the main thread, but you are accessing it from another thread. You need to create it inside the run() thread method. The place where the socket is defined does not matter. It will be created from the main thread when the C ++ runtime library statically initializes the object.

 QTcpSocket * tcpSocket; ... void FortuneThread::run() { tcpSocket = new QTcpSocket; ... } 
+4
source share

I agree with Kuba Ober . You should read that excellent guide on Qt threads, objects, and events. In particular, the section Signals and slots in streams . The authors recommend dividing the controller and the working parts into different entities.

The second problem is the code sensitive code name. Change it to readyRead .

+2
source share

The problem with the Qt Fortune Threaded Server example is the way it uses threads. As the Qt developers say, “You are doing it wrong”

The problem is QThread inheritance. The QThread class is not really a thread, but the thread controller class and the only reason to inherit it is if you want to change the flow control behavior.

The problem you see is related to thread similarity; to which the object belongs.

If the stream is inherited as follows: -

 class FortuneThread : public QThread { Q_OBJECT private: QTcpSocket tcpSocket; }; 

The FortuneThread object is then created from the main thread: -

 FortuneThread* ft = new FortuneThread(parent); 

Merging threads for the thread and the objects that it created (tcpSocket) is now the main thread, so tcpSocket is working in the main thread, which indicates an error. The start function is called at the point, the connection is from FortuneThread, but tcpSocket is in the main thread.

The best way to solve this is to create your own class derived from QObject and move it to the stream: -

 // Inherit from QObject, not QThread class FortuneSocket : public QObject { Q_OBJECT public slots: void Run(); private: QTcpSocket tcpSocket; }; QThread* pThread = new QThread(parent); FortuneSocket* pFortune = new FortuneSocket(parent); connect(pThread, &QThread::started, pFortune, &FortuneSocket::Run); // Qt5 connect style // move the fortune socket to the thread: - pFortune->moveToThread(pThread); 

Now when you start the thread using pThread-> start (), the FortuneSocket object and all its members are working in the new thread.

Using threads in this way also means that you can move multiple objects into one stream, instead of having one object in a stream. Note that creating more threads than CPU cores is pointless!

Finally, there is a more detailed article on how to use QThread, here .

+1
source share

All Articles