QtConcurrent and moveToThread



  • Hi,

    In my application, the whole user work session is managed by a graph of QObjects.

    I have a write/read function to save/load the user work session from/to an xml file.

    So, when the read function is executed, the xml file is parsed and QObjects are created to restore the user work session.

    Everything works correcly... but... with a big xml file, the loading time can be long (10s-30s, also due to other ressources loading and some pre-processing), so I would like to load the file from a worker thread (so the GUI isn't freezed)

    To do that, I use "QtConcurrent::run" to execute the read function, but I'm facing a problem : all QObjects created by the read function belongs to the QtConcurrent worker thread.

    I tried to "moveToThread" all objects to the "QApplication::instance()->thread()" while they are created by the read function.

    The problem is only partially solved. For example if we have "A" class with constructor defined as following :

    @A::A()
    {
    p_mySocket = new QTcpSocket();
    }@

    Then the read function read an "A" instance from the XML file and execute :

    @
    ...
    XML parsing
    ...
    Found "A" instance tag
    ...
    A* pA = new A();
    pA->moveToThread(QApplication::instance()->thread())
    ...
    XML parsing
    ...
    @

    => the problem is about the "p_mySocket " object : it still belongs to the QtConcurrent worker thread.
    => I can't editall my classes to implement a "moveToMainThread" method which move all the class members to the main thread

    So my questions are :

    1/ is there anyway to move ALL objects that belongs to a thread to another ?

    2/ is there anyway to know the list of ALL objects that belongs to a specific thread ? (for debugging purpose : check if all objects have been moved to the main thread)

    3/ after the "QtConcurrent::run" execution finished, is the worker thread deleted ? So what happen to all objects that belongs to this thread ?

    Thanks.



    1. if you create all your QObjects in the worker threads on the heap and then put the pointers to those objects in a QList owned by an object that resides in your main thread I don't see any problems. The QObjects will be alive until you explicitly call delete on them (with the exception that, if these QObjects have a parent, they are deleted when their parent is deleted). Finally you can iterate over the list and move every object to the main thread context.


  • The problem is that all objects created in the worker thread belongs to this thread.

    Because this thread is deleted (or no more running, i'm not sure) after the “QtConcurrent::run” execution finished, there is no more event loop executed for this thread, and SIGNAL/SLOT can never be receive/send from/to these objects.

    (executing "connect" without the connection type will make a QueuedConnection, and because of the lack of an event loop, the message is never received)

    This break SIGNAL/SLOT functionnality, and have other side effects.

    For the moment, my main goal is to write a function which check if I didn't forget to move an object to the main thread.



  • You could create the objects inside the others with a parent pointer:

    @
    A::A()
    {
    p_mySocket = new QTcpSocket(this);
    }
    @

    This would also take those to the main thread.



  • Yes, but the problem is that I have about hundred classes to check, and I did'nt write all of them... so I need at least an automatic check.



  • AFAIK, there is no automatic check, sorry.

    From my POV, if it is a requirements to go that way, you must change the code as these are programming errors in that case.



  • bq. you must change the code as these are programming errors in that case

    I agree, but in front of the huge number of files, I cannot be sure that no object was not moved to the main thread.



  • I know such things, but I have no other proposal then:

    check each usage and file :-(


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.