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. Crash when updating QGraphicsScene in a thread
Forum Updated to NodeBB v4.3 + New Features

Crash when updating QGraphicsScene in a thread

Scheduled Pinned Locked Moved General and Desktop
10 Posts 3 Posters 6.9k 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.
  • B Offline
    B Offline
    Batox
    wrote on last edited by
    #1

    On Windows 7 64 bit using Qt 4.8.4 I try to defer the updating of a pretty big QGraphicsScene to a thread, so that the main app can immediately continue. I want the drawing to take place in the background.

    I wrote a little test app to reproduce the problem. The test app also produces a crash, but a different one from the main app. The test app crashes on application exit, the message says something about sending signals to objects belonging to a different thread. In my real application it happens on scene->clear(). I hope the two effects are related, so what's wrong in the following code (Just remove the two slashes in front of "#define crash'):

    File mainwin.h:
    @class mainWin : public QMainWindow {
    Q_OBJECT

    public:
    mainWin(QWidget *parent = 0) : QMainWindow(parent) {
    QWidget *widget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(widget);
    QPushButton *btn = new QPushButton("Redraw");

      view = new QGraphicsView(widget);
      scene = new QGraphicsScene(this);
      layout->addWidget(view);
      layout->addWidget(btn);
      scene->addText("Test");
      view->setScene(scene);
    
      setCentralWidget(widget);
      connect(btn, SIGNAL(clicked()), this, SLOT(redraw()));
      countClicks = 0;
    };
    
    ~mainWin() {};
    
    virtual void doRedraw() {
      scene->clear();
      scene->addText("Test " + QString::number(countClicks++));
    };
    

    public slots:
    virtual void redraw() {
    //#define crash
    #ifdef crash
    QtConcurrent::run(this, &mainWin::doRedraw);
    #else
    doRedraw();
    #endif
    };

    private:
    QGraphicsView *view;
    QGraphicsScene *scene;
    int countClicks;
    };
    @

    File main.cpp:
    @#include "mainwin.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    mainWin *w = new mainWin;
    w->show();
    a.exec();
    }
    @

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      QGraphicsScene (and most GUI classes) are not thread-safe. They must be used from the main thread only, i.e. painting must be done in the main thread (that's why it's also called the "GUI thread").

      In your code, your QGraphicsView could be trying to read the QGraphicsScene, while the latter is being updated in the other thread -- thus you get data corruption.

      Anyway, QGraphicsScene is supposed to be highly-optimized to handle a large number of graphical objects. How bad is the delay in your app? One option is to keep the painting in the main thread, and move data-processing to a secondary thread.

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Batox
        wrote on last edited by
        #3

        Drawing the scenes (actually there are four scenes with ~300 objects in each) takes about 4 seconds. Drawing does next to no calculation (just a few trivial sums and comparisons). The delay is not huge, but the user can feel it and he thinks that it's not necessary, since drawing in a background process should really be possible.

        At this point I guess that double buffering should be the easiest way to do this. The background thread draws to a second set of scenes (which is not connected to the view) and on completion the main thread switches scenes.

        Would this be possible (are scenes thread-safe while not connected to the UI?), or is there an even simpler way to accomplish what I need?

        1 Reply Last reply
        0
        • U Offline
          U Offline
          utcenter
          wrote on last edited by
          #4

          It is strange that so few objects take so long to render? Can you post an image to get an idea of the complexity? Maybe QGS is not the best suited approach here.

          1 Reply Last reply
          0
          • B Offline
            B Offline
            Batox
            wrote on last edited by
            #5

            Thanks for the replies. It turns out that adding just a few calls to qApp->processEvents() in redraw() does the job. It's a pity, I was already hoping to learn the mutithread interface of Qt, but no need to climb that hill (yet) :).

            1 Reply Last reply
            0
            • U Offline
              U Offline
              utcenter
              wrote on last edited by
              #6

              Keep in mind that when using signals and slots to communicate between threads, the default connection is queued, which is dreadfully slow, I've had cases where multi-threaded computation were totally crippled by the bottleneck of signals and slots. Multithreaded workloads must not be very fine grained, and whenever possible avoid signals and slots for transferring data and instead use mutexes (or .. mutices???) and locks, leave signals and slots... well for signaling.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Batox
                wrote on last edited by
                #7

                [quote author="utcenter" date="1361099369"]Keep in mind that when using signals and slots to communicate between threads, the default connection is queued, which is dreadfully slow, [..] whenever possible avoid signals and slots for transferring data and instead use mutexes (or .. mutices???) and locks, leave signals and slots... well for signaling.[/quote]

                Thanks a lot for your point about preferring the classic means for data transfer - I'd probably have gone for signal/slots first, as you guessed.

                Btw, I just added a little counter to my scene drawing - it's actually over 2000 objects in total (mostly texts and boxes around them, with quite a lot of styling like different fonts, sizes and alignments), so I guess 3 seconds isn't really that bad (and on a 5 years old computer too). If I had to do that from scratch again I'd probably use the designer and place a lot of labels in boxes, because the layout is static, then I'd just have to update label texts when data changes. OTOH I feel my approach is more flexible, I have more freedom to place things outside the pattern where some Layout would put them.

                P.S. I'd guess "mutexes" is correct, but "mutices" sounds much better - I'm going to use that in the future :)

                1 Reply Last reply
                0
                • U Offline
                  U Offline
                  utcenter
                  wrote on last edited by
                  #8

                  Well, if your PC is old, that would example the low performance somewhat... but still this seems slow to me, it sounds like a lot of potential to optimize.

                  1 Reply Last reply
                  0
                  • JKSHJ Offline
                    JKSHJ Offline
                    JKSH
                    Moderators
                    wrote on last edited by
                    #9

                    Would you be willing to show us the contents of your redraw() function?

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      Batox
                      wrote on last edited by
                      #10

                      [quote author="JKSH" date="1361103013"]Would you be willing to show us the contents of your redraw() function?[/quote]

                      Although I appreciate your interest very much and would be interested in discussing more details with you, I fear I can't do that easily.

                      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