Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt 4.8 threading, QObject::setParent: Cannot set parent, new parent is in a different thread
Forum Updated to NodeBB v4.3 + New Features

Qt 4.8 threading, QObject::setParent: Cannot set parent, new parent is in a different thread

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 8.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    candll
    wrote on last edited by
    #1

    I have the following class that I want to later move to a different thread to do it's work so I don't stall the UI thread.

    @class ParserXYZ : public IParser
    {
    public:
    ParserXYZ();
    virtual ~ParserXYZ();
    virtual void loadData(const QByteArray &data);
    virtual void parse();
    virtual int getStatus(); //status of parsing, success, error, etc.
    virtual QList<Item*> getResult(); //result of parsing
    };@

    My ParserXYZ is hosted in another class, as a member variable.

    @class DataGatherer : public QObject
    {
    Q_OBJECT
    public:
    DataGatherer(IParser *parser, QObject parent=0);
    virtual ~DataGatherer();
    void start(const QByteArray &data);
    signals:
    void finished(QList<Item
    >);
    private slots:
    onParserWorkerFinished();
    private:
    IParser *m_parser;
    };@

    I made a worker class to to wrap ParserXYZ.

    @class ParserWorker : public QObject {
    Q_OBJECT
    public:
    ParserWorker(IParser *parser, const QByteArray &data);
    virtual ~ParserWorker();
    signals:
    void finished();
    public slots:
    void start();
    private:
    IParser *m_parser;
    QByteArray m_data;
    };@

    The methods that orchestrate everything:

    @//[1]
    void DataGatherer::start(const QByteArray &data)
    {
    QThread *thread = new QThread(this);
    ParserWorker *worker = new ParserWorker(m_parser, data);
    worker->moveToThread(thread);
    connect(thread, SIGNAL(started()), worker, SLOT(start()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    connect(worker, SIGNAL(finished()), this, SLOT(onParserWorkerFinished()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    thread->start();
    }

    //[2]
    void ParserWorker::start()
    {
    m_parser->loadData(m_data);
    m_parser->parse();
    emit finished();
    }

    //[3]
    void DataGatherer::onParserWorkerFinished()
    {
    if (m_parser->getStatus() == 1) {
    //was OK
    emit finished(m_parser->getResult());
    }
    }@

    In a different part of the application, I connect to the DataGatherer's finished slot:

    @connect(m_dataGatherer, SIGNAL(finished(QList<Item*>)), this, SLOT(onDataGathererFinished(QList<Item*>)));

    void onDataGathererFinished(QList<Item*> items)
    {
       foreach(Item *item, items) 
       {
          this->insert(item); //this adds elements to a ListView's DataModel
          // insert method takes ownership of each Item
          // alerts: QObject::setParent: Cannot set parent, new parent is in a different thread
    

    }
    }@

    In my case, @//[3] void DataGatherer::onParserWorkerCompleted() @ method seems to return on the background thread, not on my main thread. Later when I pump data further via signals I eventually want to add items to a UI element and the program crashes alerting that I am attempting to setParent on an element on a different thread. How can I ensure that my signals return on the main thread?

    1 Reply Last reply
    0
    • B Offline
      B Offline
      bodzio131
      wrote on last edited by
      #2

      Are you sure that the slot is called in the background thread? In my opinion you have created some qobjects (the result) in the background thread and you are trying to re-parent them in the different thread. Look for Qt warning "QObject::setParent: Cannot set parent, new parent is in a different thread" in Qt sources, there is simple clue: "object hierarchies are constrained to a single thread".

      1 Reply Last reply
      0
      • C Offline
        C Offline
        candll
        wrote on last edited by
        #3

        Hm, well the "Item" QObjects are in fact created in the background thread (via the parser class), but without any parent. Later, in the foreach loop they are getting implicitly reparented by the "insert" method. Would not using QObjects as return values for the parser be the solution?.
        [quote author="Bogdan" date="1370617157"]Are you sure that the slot is called in the background thread? In my opinion you have created some qobjects (the result) in the background thread and you are trying to re-parent them in the different thread. Look for Qt warning "QObject::setParent: Cannot set parent, new parent is in a different thread" in Qt sources, there is simple clue: "object hierarchies are constrained to a single thread".[/quote]

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bodzio131
          wrote on last edited by
          #4

          bq. Would not using QObjects as return values for the parser be the solution?

          Well, I hope so :) From the other side of the fence consider such thing: why would you want to couple parser result with QObject? Is this dependency really needed? When I'm thinking about parser result then I get rather some simple tokens, not heavy, full-featured QObjects.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved