[solved] Question regarding threading example: How to make an object "live" in a thread permanently?



  • I just took a look at "Threading Basics - Example 4: A Permanent Thread":http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html#example-4-a-permanent-thread .

    I have a singleton in my application, derived from QObject. And I would like to make it do all it's work in a different thread. The linked example seems to be a good starting point, but based on what I know about QThreads, I wouldn't know how the Thread-class mentioned in the example could work.

    The goal is to have an object live in a thread, or, (maybe?) even better, have it run all it's functions in a different thread and reside in the main thread when doing nothing.

    Going back to the example, what would
    @thread.launchWorker(worker);@

    do to make this thing work? The QMetaObject::invokeMethod() part looks like it might be what I need.

    I am not yet sure how to tackle this problem in the most elegant way, so I would welcome any ideas for a better solution. :)


  • Moderators

    Hi,

    That example is more convoluted than it needs to be, IMHO. It says that launchWorker() moves the worker and starts the thread, but we already have a ready-to-use solution to accomplish that. Just write:
    @
    int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QThread thread;
    mySingleton->instance()->moveToThread(&thread);
    thread.start();
    
    // Initialize other stuff
    ...
    
    // Run the main event loop
    int exitCode = app.exec();
    
    // Clean up the thread after the main event loop quits
    thread.quit();
    thread.wait();
    
    return exitCode;
    

    }
    @

    Then, whenever you want to run one of your singleton's functions, either trigger the function using a signal-slot connection, or call the function through QMetaObject::invokeMethod(). If you call the function directly, it will run in the calling thread, which is probably not what you want.

    [quote author="thEClaw" date="1378754952"]The goal is to have an object live in a thread, or, (maybe?) even better, have it run all it's functions in a different thread and reside in the main thread when doing nothing.[/quote]I can't see any benefits from having the object move around threads based on whether it's busy or idle.



  • Thanks a lot, I will immediately test this. QThreads do confuse me every time I need them, with several contradictory things I have read about them in the past. One of the few points where I dare to question the documentation from time to time.

    I still have a couple of questions:
    1. The thread in your example doesn't have a parent, is there a reason for that?

    2. I have never used a thread without connecting anything to it's QThread::started() Signal, that's why the solution you gave didn't even occur to me. Does this method actually just create a thread with a fully functioning event loop?

    3. Concerning the periodic moving between threads: Are there any drawbacks due to my application using more than one thread continuously?



  • 1.) Since the QThread object is created on the stack it does not need a parent for destruction.
    2.) Yes
    3.)What do you think. Is it more work to just leave stuff as it is when the worker object and the second thread are idle. Or is it more work to move the object around and destroy and recreate a new thread everytime the worker object changes its state from idle to working and vice versa ?



  • I tried the solution you gave, and everything seems to work fine. So thanks again. :)

    I don't know if it is more expensive to create/destroy the thread from time to time or just have it "running" in the background - I have no idea how many resources it is using up when idle.



  • Hmm. I guess it depends on your use case scenario. How often the worker object switches its state form idle to working, how long the idle state lasts and so on. But I don't think this kind of performance concerns are neccessary. Moving the object and recreating threads would just add an extra layer of complexity and might add additional sources for bugs in your code.



  • Since I am using additional threads at some other point too, I will read up on QRunnable and QtConcurrent.
    Regarding the thread you just helped me create, I am using it to run a script-parser (asked about implementing that a couple of days ago), which could lock up my application for several seconds, so moving it to another thread was a must. It is not frequently used, however. Maybe I can use that same thread for other tasks too?

    Anyway. Thanks for your help, again. If I run into more questions regarding my thread management, I may open up another thread.



  • Maybe you can use a thread pool to manage all your threads and just distribute the work evenly over the available threads. Have a look at "QThreadPool":http://qt-project.org/doc/qt-4.8/qthreadpool.html and see if it fits you or maybe you want to implement your own thread pool to manage your QThread instances.


  • Moderators

    [quote author="thEClaw" date="1378794477"]Thanks a lot, I will immediately test this. QThreads do confuse me every time I need them, with several contradictory things I have read about them in the past. One of the few points where I dare to question the documentation from time to time.[/quote]It is a complicated subject so the community spent quite a while trying to figure out the best way to do things :) Along the way, many opinions were given and many debates were run. I think the latest documentation provides quite a holistic treatment of the subject; it touches on different viewpoints: http://qt-project.org/doc/qt-5.1/qtcore/qthread.html

    But anyway, Qt is awesome but not perfect. If something you read conjures question marks, feel free to question it on the forum. There are two possible outcomes: (i) You understand the topic much quicker, or (ii) You highlight an error than can then be fixed.

    [quote author="KA51O" date="1378798795"]1.) Since the QThread object is created on the stack it does not need a parent for destruction.[/quote]To expand on KA51O's answer, parent-child relationships specify ownership of QObjects. This provides automatic memory management -- when a parent gets deleted, so will its children. However, stack-allocated objects get automatically be deleted anyway when they go out of scope.

    See http://qt-project.org/doc/qt-5.1/qtcore/objecttrees.html for more details.

    [quote author="thEClaw" date="1378794477"]2. Does this method actually just create a thread with a fully functioning event loop?[/quote]Yep. From the "QThread documentation":http://qt-project.org/doc/qt-5.1/qtcore/qthread.html:

    • QThread::start(): "Begins execution of the thread by calling run()"
    • QThread::run(): "The default implementation simply calls exec()"
    • QThread::exec(): "Enters the event loop and waits until exit() is called"

    [quote author="thEClaw" date="1378800695"]I don't know if it is more expensive to create/destroy the thread from time to time or just have it "running" in the background - I have no idea how many resources it is using up when idle.[/quote]Throughout the internet, you will find many forum posts along the lines of, "which is faster/more efficient/less resource-hungry?"

    The correct answer is, "Profile it".

    [quote author="thEClaw" date="1378804589"]I am using it to run a script-parser (asked about implementing that a couple of days ago), which could lock up my application for several seconds, so moving it to another thread was a must. It is not frequently used, however. Maybe I can use that same thread for other tasks too?[/quote]The Qt event loop is pretty efficient -- if nothing is running in the thread, it doesn't consume anything noticeable. I wouldn't agonize over the overhead required to maintain one idle thread, unless your program is running on a resource-starved embedded system.

    You can move as many unrelated objects to that thread as you want -- all of their slots will run in that thread if invoked properly.



  • [quote author="JKSH" date="1378810034"]But anyway, Qt is awesome but not perfect. If something you read conjures question marks, feel free to question it on the forum. There are two possible outcomes: (i) You understand the topic much quicker, or (ii) You highlight an error than can then be fixed.[/quote]
    The newest documentation has a lot of "unlinked" information, e.g. often the classes inheriting from a parent are not fully listed (which is a huge drawback when clicking through the documentation in search of something to fit current needs), or QString::fromWchar() is nowhere to be found (even though it exists). Where to go with complaints like that?

    [quote author="JKSH" date="1378810034"]To expand on KA51O's answer, parent-child relationships specify ownership of QObjects. This provides automatic memory management -- when a parent gets deleted, so will its children. However, stack-allocated objects get automatically be deleted anyway when they go out of scope.[/quote]
    The basics of that are known to me, but I always wondered about something: Does a Qt class usually need a destructor? Anything I derive should be cleanly deleted as long as I correctly parent all its children, right?

    A huge thanks for your information and the links you provided, I rarely stumble upon the basic/background articles, and I hadn't seen the one on QObjects before. The QThread documentation is actually a lot more complete than it was in 4.8, as far as I remember.
    I will stop worrying about that idle thread for now, at least the code is simple in its current state. :)


  • Moderators

    [quote author="thEClaw" date="1378820439"]The newest documentation has a lot of "unlinked" information, e.g. often the classes inheriting from a parent are not fully listed (which is a huge drawback when clicking through the documentation in search of something to fit current needs), or QString::fromWchar() is nowhere to be found (even though it exists). Where to go with complaints like that?[/quote]Reports go to https://bugreports.qt-project.org/secure/Dashboard.jspa

    But first, check that it hasn't already been reported, and that it hasn't already been fixed. This link contains the very latest (prerelease) version of the documentation and is updated almost daily: http://doc-snapshot.qt-project.org/qt5-dev/qtdoc/index.html

    The broken links were a side effect of Qt 5 getting modularized (the doc generator was not designed to handle modules), but there are efforts to address that for the Qt 5.2 release. See http://comments.gmane.org/gmane.comp.lib.qt.devel/12843 for details.

    [quote]Does a Qt class usually need a destructor? Anything I derive should be cleanly deleted as long as I correctly parent all its children, right?[/quote]Do you mean:

    • "Do I need to implement a destructor?", or
    • "Do I need to destroy my objects manually?"

    QObjects (including ones that you derive yourself) that have a parent will be deleted with the parent. However, be aware that there are many non-QObjects in the Qt library, which don't have this feature.

    Also, you will sometimes receive ownership of a QObject that doesn't have a parent. For example, when you call QNetworkAccessManager::get(), it returns a pointer to a QNetworkReply. The documentation states, "After the request has finished, it is the responsibility of the user to delete the QNetworkReply object at an appropriate time."

    Even though an object might be deleted automatically, you still need to implement a destructor if you have any heap-allocated non-QObjects. You may also want to implement some cleanup code that runs before the object is destroyed.

    [quote]A huge thanks for your information and the links you provided, I rarely stumble upon the basic/background articles, and I hadn't seen the one on QObjects before. The QThread documentation is actually a lot more complete than it was in 4.8, as far as I remember.
    I will stop worrying about that idle thread for now, at least the code is simple in its current state. :)[/quote]You're welcome :) Overviews are at https://qt-project.org/doc/qt-5.1/qtdoc/overviews-main.html

    Also, Qt Assistant (the offline help viewer) has a decent search feature


Log in to reply
 

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