QThread or std::thread?



  • Hello Qt community,

    I was wondering which type of thread I should use for my project. The main thread would be processing the Qt loop, and the other threads would basically update variables and such (Positions, QPixmaps, etc.)

    Is there an important difference(s) I should be aware of? std::thread sounds much easier to use...



  • If you are going to communicate using signals and slots (what you should) than you need QThread.



  • Oh, is it as simple as that? Because I think I'm not going to use signals and slots.



  • @Pippin How are you going to report to the main event loop, that the position, or pixmap changed? Or if you will use QRunnable than you are back with signal/slots. I would stick with QThread since it makes things easier and more compact. You can also start another eventloop in next thread and let computing running there. See http://thesmithfam.org/blog/2010/02/07/talking-to-qt-threads/



  • Well everything that the other threads would be updating are QGraphicsItems that would be displayed inside a QGraphicsView. I was going to disable the automatic update of the Viewport

    myView.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
    

    then update it whenever necessary:

    myView.update();
    

    Is it okay?



  • @Pippin
    never mix Qt event loop with std::threads. it just doesn't work together.
    Qt has all the async functions you need, similar syntax to std.


  • Moderators

    @Pippin said:

    Well everything that the other threads would be updating are QGraphicsItems that would be displayed inside a QGraphicsView. I was going to disable the automatic update of the Viewport

    myView.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
    

    then update it whenever necessary:

    myView.update();
    

    Is it okay?

    All GUI-related classes must be used in the GUI thread only. (The GUI thread is the one which created the QApplication.) You cannot use them in other threads.



  • @JKSH Not sure what you're telling me: are you telling me that I must use QThreads, or are you telling me that even QThreads won't let me modify other QObjects?


  • Moderators

    @Pippin said:

    @JKSH Not sure what you're telling me: are you telling me that I must use QThreads, or are you telling me that even QThreads won't let me modify other QObjects?

    I mean you cannot create QGraphicsView/GraphicsItem/QPixmap in another thread, and you cannot call those class' methods in another thread. This rule applies regardless of whether you use QThread or std::thread.

    Anyway, the Graphics View Framework is designed to handle lots of items at the same time. Perhaps you don't need threads at all?



  • @JKSH Oh wow, I wasn't aware of this. That sounds very problematic. Also, why is this not mentioned in pages like http://doc.qt.io/qt-5/qtconcurrentrun.html ?

    The thing is, my project displays moving cards (QPixmaps) inside a QGraphicsScene/QGraphicsView instance, and I must control the FPS rate so that cards are always moving at the same speed. The (basic) idea is to slightly move 1 or more card(s), then update the QGraphicsView, then sleep, then slightly move 1 or more card(s) again, etc. at a given, fixed FPS rate so that the moving always looks natural. This is why I need another thread that computes the new positions, then update the view (so that the main thread draws it), then sleep, then repeat.

    How can I do that?


  • Moderators

    @Pippin said:

    I must control the FPS rate so that cards are always moving at the same speed. The (basic) idea is to slightly move 1 or more card(s), then update the QGraphicsView, then sleep, then slightly move 1 or more card(s) again, etc. at a given, fixed FPS rate so that the moving always looks natural. This is why I need another thread that computes the new positions, then update the view (so that the main thread draws it), then sleep, then repeat.

    How can I do that?

    Have a look at the animations framework: http://doc.qt.io/qt-5/animation-overview.html You don't need to calculate every frame yourself



  • @Pippin Qt offers different solutions to use Threads. Here you can find an overview of the 4 solutions and a table that helps you to choose the best for your needs



  • @JKSH I've just used QtConcurrent to launch a function that makes a window visible and changes the background of a QGraphicsView, and there was no problem. I don't understand, because according to you my attempt should have failed. What am I missing?

    Also, the following code can't seem to work:

    	QThreadPool *pool;
    	QFuture<void> future = QtConcurrent::run(pool, foo2);
    

    where foo2 is a void function without arguments. The compilation report is quite long and can be found here: http://pastebin.com/Sq35HD0v

    I don't understand how I'm not using QtConcurrent::run() correctly. However the following code works:

    	QFuture<void> future = QtConcurrent::run(foo2);
    

    If someone sees the catch, feel free to point it out. Thanks.


  • Moderators

    @Pippin said:

    @JKSH I've just used QtConcurrent to launch a function that makes a window visible and changes the background of a QGraphicsView, and there was no problem. I don't understand, because according to you my attempt should have failed. What am I missing?

    The thing is, it's not guaranteed to fail immediately. Manipulating GUI classes in a different thread leads to undefined behaviour. That means, sometimes it might work as you'd expect, but it might crash at other times.

    See the documentation: "Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread."

    Also, the following code can't seem to work:

    	QThreadPool *pool;
    	QFuture<void> future = QtConcurrent::run(pool, foo2);
    

    where foo2 is a void function without arguments. The compilation report is quite long and can be found here: http://pastebin.com/Sq35HD0v

    That overload of QtConcurrent::run() was introduced in Qt 5.4.0: http://code.qt.io/cgit/qt/qtbase.git/tree/dist/changes-5.4.0 (so it won't compile with older versions of Qt)


  • Moderators

    @Pippin
    This cannot work:

    QThreadPool *pool;
    QFuture<void> future = QtConcurrent::run(pool, foo2);
    

    You did not create an instance of QThreadPool.



  • @jsulm Fair point, thanks.

    @JKSH Ok thanks. It's weird though, because I've installed Qt very recently, I would have thought that I had Qt 5.5 already.


Log in to reply
 

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