Results 1 to 7 of 7

Thread: [QTcpSocket] Cannot create children for a parent that is in a different thread

  1. #1
    Join Date
    Feb 2011
    Posts
    354
    Thanks
    17
    Thanked 27 Times in 24 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows

    Default [QTcpSocket] Cannot create children for a parent that is in a different thread

    Hello, I am trying to deal with threading affinity. I think I did everything like it was suggested in the "you're doing it wrong" article, but still I receive error messages from the socket when I call waitForConnected method:
    "QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QTcpSocket(0x2022608), parent's thread is QThread(0x1fc8320), current thread is QThread(0x40fde8)"

    Here is my code, I create controller class that is executed in the separate thread.
    Qt Code:
    1. test::test(QWidget *parent, Qt::WFlags flags)
    2. : QMainWindow(parent, flags)
    3. {
    4. ui.setupUi(this);
    5.  
    6. controller = new Controller();
    7. controller->moveToThread(&thread);
    8. connect(&thread, SIGNAL(started()), controller, SLOT(start()));
    9. connect(controller, SIGNAL(finished()), &thread, SLOT(quit()));
    10.  
    11. connect(this, SIGNAL(fileAdded(const QString &)), controller, SLOT(enqueueFile(const QString &)));
    12.  
    13. emit fileAdded("lalalala");
    14.  
    15. thread.start();
    16. }
    To copy to clipboard, switch view to plain text mode 

    Controller class declaration:
    Qt Code:
    1. #ifndef CONTROLLER_H
    2. #define CONTROLLER_H
    3.  
    4. #include <QThread>
    5. #include <QTcpSocket>
    6.  
    7. class Controller: public QObject
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. Controller(QObject *parent = 0);
    13. ~Controller();
    14.  
    15. public slots:
    16. void enqueueFile(const QString &fileName);
    17. void start();
    18.  
    19. signals:
    20. void finished();
    21.  
    22.  
    23. private:
    24. QTcpSocket socket;
    25. };
    26.  
    27. #endif // CONTROLLER_H
    To copy to clipboard, switch view to plain text mode 

    Controller class implementation:
    Qt Code:
    1. #include "controller.h"
    2.  
    3. #include <QDebug>
    4. #include <QTimer>
    5. #include <QEventLoop>
    6.  
    7. Controller::Controller(QObject *parent)
    8. {
    9.  
    10. }
    11.  
    12. Controller::~Controller()
    13. {
    14.  
    15. }
    16.  
    17. void Controller::start()
    18. {
    19. socket.connectToHost("some-host", 777);
    20. socket.waitForConnected(); // here goes the error
    21. socket.disconnectFromHost();
    22. socket.waitForDisconnected(); // here goes the error again
    23. }
    24.  
    25. void Controller::enqueueFile(const QString &fileName)
    26. {
    27. qDebug() << fileName;
    28. }
    To copy to clipboard, switch view to plain text mode 

    I know threads are not really needed for sockets, I could use signal/slot mechanism, but this is just for test. Please help me to understand what is wrong.

  2. #2
    Join Date
    Dec 2011
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    Did you ever find a solution? I'm in a similar spot. I have a class that polls a serial port for data. Upon receiving data, it passes it to another class to analyze the data. The Analyze class emits a signal if the data requires logging. A third class, Logger, has a slot for the data to log it to a web server. I separated the Logger class so I could possibly use it elsewhere within the program.

    Currently, I'm loading the Polling class in main and shuffling it off to the globalInstace of QThreadPool. I load up the other two classes within the Polling class and connect the SIGNAL/SLOT there.

  3. #3
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    I think the problem in the OP is that socket is not a child of Controller, and so it has been 'left behind' in the old thread.

    I think this would solve the problem
    Qt Code:
    1. Controller::Controller(QObject *parent)
    2. : socket(this)
    3. {
    4. }
    To copy to clipboard, switch view to plain text mode 
    If your compiler supports it, otherwise

    Qt Code:
    1. Controller::Controller(QObject *parent)
    2. {
    3. socket.setParent(this);
    4. }
    To copy to clipboard, switch view to plain text mode 
    should be ok as well.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  4. #4
    Join Date
    Dec 2011
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    Thanks amieto!

    What's happening now for me, is the SIGNAL from Analyzer appears to be emitted, but the SLOT in Logger never gets run.

    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include <QThread>
    3. #include "logger.h"
    4. #include "pollcontroller.h"
    5. #include "analyzer.h"
    6.  
    7. int main(int argc, char *argv[])
    8. {
    9. QCoreApplication a(argc, argv);
    10.  
    11. QString host = "web-dev";
    12. int port = 85;
    13.  
    14. PollController *pollController = new PollController();
    15. pollController->setup(1,1000);
    16. Analyzer *analyzer = pollController->getAnalyzer();
    17.  
    18. QThread pollThread;
    19. pollController->moveToThread(&pollThread);
    20.  
    21. Logger *logger = new Logger();
    22. logger->setup(host,port,analyzer);
    23.  
    24. QThread loggerThread;
    25. logger->moveToThread(&loggerThread);
    26.  
    27. return a.exec();
    28. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #ifndef POLLCONTROLLER_H
    2. #define POLLCONTROLLER_H
    3.  
    4. #include <QObject>
    5. #include <QThread>
    6. #include "analyzer.h"
    7. #include "sleep.h"
    8.  
    9. class PollController : public QObject
    10. {
    11. Q_OBJECT
    12. public:
    13. explicit PollController(QObject *parent = 0);
    14. void setup(int,int);
    15. Analyzer*& getAnalyzer();
    16.  
    17. signals:
    18.  
    19. public slots:
    20.  
    21. private:
    22. void loopNumbers(int,int);
    23. Analyzer *analyzer;
    24.  
    25. };
    26.  
    27. #endif // POLLCONTROLLER_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "pollcontroller.h"
    2.  
    3. PollController::PollController(QObject *parent) :
    4. QObject(parent)
    5. {
    6. }
    7.  
    8. void PollController::setup(int begin, int end) {
    9. analyzer = new Analyzer(this);
    10. loopNumbers(begin,end);
    11. }
    12.  
    13. void PollController::loopNumbers(int begin, int end) {
    14. Sleep sleep;
    15. QString logMsg = "99.00.050.01.*";
    16. QString skipMsg = "99.00.121.01.03939021";
    17.  
    18. // Generate some data to check
    19. for (int x=begin; x<end; x++) {
    20. qDebug() << "poll received:" << x;
    21.  
    22. if (x % 4 == 0) {
    23. analyzer->analyze(logMsg);
    24. } else if (x % 2 == 0) {
    25. analyzer->analyze(skipMsg);
    26. }
    27.  
    28. sleep.msleep(1000);
    29. }
    30. }
    31.  
    32. Analyzer*& PollController::getAnalyzer() {
    33. return analyzer;
    34. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #ifndef ANALYZER_H
    2. #define ANALYZER_H
    3.  
    4. #include <QObject>
    5. #include <QDebug>
    6.  
    7. class Analyzer : public QObject
    8. {
    9. Q_OBJECT
    10. public:
    11. explicit Analyzer(QObject *parent = 0);
    12. void analyze(QString&);
    13.  
    14. signals:
    15. void msgToLog(QString&);
    16.  
    17. public slots:
    18.  
    19. };
    20.  
    21. #endif // ANALYZER_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "analyzer.h"
    2. #include <QStringList>
    3.  
    4. Analyzer::Analyzer(QObject *parent) :
    5. QObject(parent)
    6. {
    7. }
    8.  
    9. void Analyzer::analyze(QString &msg)
    10. {
    11. if (msg.contains(".")) {
    12. QStringList fields = msg.split(".");
    13.  
    14. if (fields.at(2) == "050") {
    15. emit(msgToLog(msg));
    16. qDebug() << "emit(msgToLog(msg))";
    17. return;
    18. }
    19.  
    20. qDebug() << "msg" << msg << "didn't contain 050 command";
    21. }
    22. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #ifndef LOGGER_H
    2. #define LOGGER_H
    3.  
    4. #include <QObject>
    5. #include <QTcpSocket>
    6. #include <QAbstractSocket>
    7. #include <QDebug>
    8. #include "analyzer.h"
    9.  
    10. class Logger : public QObject
    11. {
    12. Q_OBJECT
    13. public:
    14. explicit Logger(QObject *parent = 0);
    15. void setup(QString&,int&,Analyzer*&);
    16.  
    17. signals:
    18.  
    19. public slots:
    20. void connected();
    21. void disconnected();
    22. void bytesWritten(qint64);
    23. void readyRead();
    24. void write(QString &msg);
    25.  
    26. private:
    27. QTcpSocket *socket;
    28. QString host;
    29. int port;
    30.  
    31. };
    32.  
    33. #endif // LOGGER_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "logger.h"
    2.  
    3. Logger::Logger(QObject *parent) :
    4. QObject(parent)
    5. {
    6. }
    7.  
    8. void Logger::setup(QString &host, int &port, Analyzer *&analyzer)
    9. {
    10. connect(analyzer,SIGNAL(msgToLog(QString&)),this,SLOT(write(QString&)),Qt::AutoConnection);
    11.  
    12. socket = new QTcpSocket(this->parent());
    13.  
    14. connect(socket,SIGNAL(connected()),this,SLOT(connected()));
    15. connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    16. connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
    17. connect(socket,SIGNAL(bytesWritten(qint64)),this,SLOT(bytesWritten(qint64)));
    18.  
    19. this->host = host;
    20. this->port = port;
    21. }
    22.  
    23. void Logger::connected()
    24. {
    25. qDebug() << "Connected";
    26. }
    27.  
    28. void Logger::disconnected()
    29. {
    30. qDebug() << "Disconnected";
    31. }
    32.  
    33. void Logger::bytesWritten(qint64)
    34. {
    35. }
    36.  
    37. void Logger::readyRead()
    38. {
    39. qDebug() << "socket readAll:" << socket->readAll();
    40. }
    41.  
    42. void Logger::write(QString &msg)
    43. {
    44. qDebug() << "write msg:" << msg;
    45.  
    46. socket->connectToHost(host,port);
    47.  
    48. if (!socket->waitForConnected(500)) {
    49. qDebug() << "Error:" << socket->errorString();
    50. return;
    51. }
    52.  
    53. QByteArray serverMsg;
    54. serverMsg.append("GET /log/test/msg/");
    55. serverMsg.append(msg);
    56. serverMsg.append("/time/1234567859 HTTP/1.0\r\n\r\n");
    57. socket->write(serverMsg);
    58. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #ifndef SLEEP_H
    2. #define SLEEP_H
    3.  
    4. #include <QWaitCondition>
    5. #include <QMutex>
    6.  
    7. class Sleep
    8. {
    9. public:
    10. Sleep();
    11. void msleep(unsigned long msecs);
    12. };
    13.  
    14. #endif // SLEEP_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "sleep.h"
    2.  
    3. Sleep::Sleep()
    4. {
    5. }
    6.  
    7. void Sleep::msleep(unsigned long msecs) {
    8. QMutex mutex;
    9. mutex.lock();
    10.  
    11. QWaitCondition waitCondition;
    12. waitCondition.wait(&mutex,msecs);
    13.  
    14. mutex.unlock();
    15. }
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Dec 2011
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    Ok. So I took a different approach. I decided to just fire up a new instance of my Logger class whenever the polling object that is running on its own thread has something to log to the web server. It seems to work in testing, I'm just wondering if I'm doing things correctly, or just getting lucky.

  6. #6
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    eewww, why are you pasing QString by reference for logging calls? Not even const reference! QString should definitely be passed by value.

    If you slot doesn't get hit, first thing you should do is debug the connections - does qt give any error message? Then debug what happens after the signal.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  7. #7
    Join Date
    Feb 2011
    Posts
    354
    Thanks
    17
    Thanked 27 Times in 24 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows

    Default Re: [QTcpSocket] Cannot create children for a parent that is in a different thread

    Well, I think I found the issue. Passing QString by reference may be something that wasn't intended, but technically it works (slot will be invoked). I think, the problem is you emit signals before establishing connection.
    Qt Code:
    1. PollController *pollController = new PollController();
    2.  
    3. // you emit signals here !
    4. pollController->setup(1,1000);
    5.  
    6. Analyzer *analyzer = pollController->getAnalyzer();
    7.  
    8.  
    9.  
    10. QThread pollThread;
    11.  
    12. pollController->moveToThread(&pollThread);
    13.  
    14.  
    15.  
    16. Logger *logger = new Logger();
    17. // you establish connection here! doesn't even get called
    18. logger->setup(host,port,analyzer);
    To copy to clipboard, switch view to plain text mode 

    However, it seems to not have any relation to my post. G00d luck.

Similar Threads

  1. Replies: 3
    Last Post: 19th March 2011, 16:01
  2. Replies: 0
    Last Post: 14th April 2010, 16:03
  3. disable a parent and children in a tree model
    By qt_gotcha in forum Newbie
    Replies: 4
    Last Post: 9th July 2009, 07:49
  4. Replies: 6
    Last Post: 8th July 2009, 14:24
  5. Replies: 4
    Last Post: 1st May 2009, 12:00

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.