QTcpSocket in Thread
-
Hi I am developing a QML application. I am developing the backend with c++. I'm trying to establish a tcp connection in a thread and make it communicate in a way that doesn't block the QML application. My code is as below. It successfully connects to the server but does not send or receive messages. What is the problem here and how can I solve it? Can a new thread be created from a class in Thread?
Output:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x2c1f5724210), parent's thread is QThread(0x2c1f5724090), current thread is QThread(0x7ff7169ff030) QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x2c1f5724210), parent's thread is QThread(0x2c1f5724090), current thread is QThread(0x7ff7169ff030)
// main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "src/user.h" QThread userThread; User user; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); user.moveToThread(&userThread); QObject::connect(&userThread, &QThread::started, &user, &User::run); userThread.start(); QQmlApplicationEngine engine; const QUrl url(u"qrc:/Make/Main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
// user.h
#ifndef USER_H #define USER_H #include <QObject> #include <QDebug> #include <QThread> #include <QTcpSocket> class User : public QObject { Q_OBJECT private: QTcpSocket *socket; public: explicit User(QObject *parent = nullptr); public slots: void run(); void readSocket(); signals: }; #endif // USER_H
// user.cpp
#include "user.h" User::User(QObject *parent) : QObject{parent} { socket = new QTcpSocket(); QObject::connect(socket, &QTcpSocket::readyRead, this, &User::readSocket); } void User::run() { for(;;) { if(!socket->isOpen()) { socket->connectToHost("127.0.0.1", 1337); if(socket->waitForConnected(3000)) { QByteArray data("Hello"); socket->write(data); } } QThread::sleep(3000); } } void User::readSocket() { if(socket->isOpen()) { QByteArray data = socket->readAll(); qDebug() << data.toStdString(); } }
-
Hi I am developing a QML application. I am developing the backend with c++. I'm trying to establish a tcp connection in a thread and make it communicate in a way that doesn't block the QML application. My code is as below. It successfully connects to the server but does not send or receive messages. What is the problem here and how can I solve it? Can a new thread be created from a class in Thread?
Output:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x2c1f5724210), parent's thread is QThread(0x2c1f5724090), current thread is QThread(0x7ff7169ff030) QObject: Cannot create children for a parent that is in a different thread. (Parent is QTcpSocket(0x2c1f5724210), parent's thread is QThread(0x2c1f5724090), current thread is QThread(0x7ff7169ff030)
// main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "src/user.h" QThread userThread; User user; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); user.moveToThread(&userThread); QObject::connect(&userThread, &QThread::started, &user, &User::run); userThread.start(); QQmlApplicationEngine engine; const QUrl url(u"qrc:/Make/Main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
// user.h
#ifndef USER_H #define USER_H #include <QObject> #include <QDebug> #include <QThread> #include <QTcpSocket> class User : public QObject { Q_OBJECT private: QTcpSocket *socket; public: explicit User(QObject *parent = nullptr); public slots: void run(); void readSocket(); signals: }; #endif // USER_H
// user.cpp
#include "user.h" User::User(QObject *parent) : QObject{parent} { socket = new QTcpSocket(); QObject::connect(socket, &QTcpSocket::readyRead, this, &User::readSocket); } void User::run() { for(;;) { if(!socket->isOpen()) { socket->connectToHost("127.0.0.1", 1337); if(socket->waitForConnected(3000)) { QByteArray data("Hello"); socket->write(data); } } QThread::sleep(3000); } } void User::readSocket() { if(socket->isOpen()) { QByteArray data = socket->readAll(); qDebug() << data.toStdString(); } }
You don't pass a parent to your QTcpSocket so moveToThread() doesn't/can't move it to the new thread since it only moves 'User' and it's children but your QTcpSocket is not a children of 'User'
-
You don't pass a parent to your QTcpSocket so moveToThread() doesn't/can't move it to the new thread since it only moves 'User' and it's children but your QTcpSocket is not a children of 'User'
@Christian-Ehrlicher So what to do?
-
@Christian-Ehrlicher So what to do?
@NullByte said in QTcpSocket in Thread:
@Christian-Ehrlicher So what to do?
consider not using threads at all.
-
@NullByte said in QTcpSocket in Thread:
@Christian-Ehrlicher So what to do?
consider not using threads at all.
@J-Hilk said in QTcpSocket in Thread:
consider not using threads at all.
For nearly every threading question on this forum (and almost every forum not concerned with high performance computing), this is the best answer.
-
@J-Hilk said in QTcpSocket in Thread:
consider not using threads at all.
For nearly every threading question on this forum (and almost every forum not concerned with high performance computing), this is the best answer.
@jeremy_k How do we do this? Is it enough to use a Signal Slot?
-
@jeremy_k How do we do this? Is it enough to use a Signal Slot?
@NullByte said in QTcpSocket in Thread:
Is it enough to use a Signal Slot?
Why should it not? It's shown in the documentation and Qt uses signals and slots everywhere.
-
-
@jeremy_k How do we do this? Is it enough to use a Signal Slot?
@NullByte said in QTcpSocket in Thread:
@jeremy_k How do we do this? Is it enough to use a Signal Slot?
- Start with connecting signals to slots using automatic connections.
- If that proves to be inadequate, profile the application to determine and quantify the issue.
- If* the cause is unavoidable blocking calls or long sections of non-decomposable logic, consider a thread** to offload that section.
* There's always an exception
** Read and understand the documentation related to QThread, QObject::moveToThread(), and in particular https://doc.qt.io/qt-6/qobject.html#thread-affinity . The error @Christian-Ehrlicher refers to has its own call-out:Note: A QObject's member variables do not automatically become its children. The parent-child relationship must be set by either passing a pointer to the child's constructor, or by calling setParent(). Without this step, the object's member variables will remain in the old thread when moveToThread() is called.