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. Keeping GUI responsive
QtWS25 Last Chance

Keeping GUI responsive

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

    Hi again!

    Basically I want to keep my GUI responsive while, for example, processing data in a loop. So I guess I would have to do that processing in another thread.

    If I want to wait for a thread to finish before continuing in my main thread I would have to use a QEventLoop, right?

    Here is my code which creates a new thread and does what it should, but doesn't seem to exit the QEventLoop ("end" doesn't get printed out):

    @ MyWorker w;
    QThread t;
    QEventLoop l;

        connect(&t, &QThread::started, &w, &MyWorker::doLotsOfStuff);
        connect(&t, &QThread::finished, &l, &QEventLoop::quit);
    
        qDebug() << "begin";
    
        w.moveToThread(&t);
    
        t.start();
        l.exec&#40;&#41;;
    
        qDebug(&#41; << "end";@
    

    What am I doing wrong?

    Help is appreciated! :)

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      t.start() calls QThread::run() in another thread, which in default implementation just calls exec(). What that means is that your thread never actually finishes and keeps going in circles after finishing doLotsOfStuff. You would need to call something like QThread::currentThread().quit() at the end of doLotsOfStuff or do something like
      @
      connect(&w, &MyWorker::someFinishedSignal, &t, &QThread::quit());
      @

      1 Reply Last reply
      0
      • X Offline
        X Offline
        xiit
        wrote on last edited by
        #3

        Oh, that makes things more clear. Thank you very much!

        1 Reply Last reply
        0
        • A Offline
          A Offline
          andre
          wrote on last edited by
          #4

          Take a look at the "example":/doc/qt-5.0/qtcore/qthread.html#details in the documentation.
          You don't need the event loop in here. Instead, create your thread and your worker on the heap (using the new keyword) and listen for a signal from your worker when it is done.

          1 Reply Last reply
          0
          • X Offline
            X Offline
            xiit
            wrote on last edited by
            #5

            Alright, I skipped the QEventLoop.

            What if I want to cancel what the thread is processing (i.e exit a loop)?

            I've added a signal to MainWindow called "abort()", added a slot to MyWorker called "abort()" and connected the both with:

            @connect(this, &MainWindow::abort, w, &MyWorker::abort);@

            And then when I click a button, I emit the signal with:

            @emit abort();@

            But whatever is in the "abort()" slot of MyWorker doesn't get executed.

            Is this the wrong way of doing it?

            1 Reply Last reply
            0
            • A Offline
              A Offline
              andre
              wrote on last edited by
              #6

              No, that is ok in principle. However, it only works if your thread actually returns to the event loop.

              1 Reply Last reply
              0
              • X Offline
                X Offline
                xiit
                wrote on last edited by
                #7

                [quote author="Andre" date="1360167554"]No, that is ok in principle. However, it only works if your thread actually returns to the event loop.[/quote]

                Would you like to elaborate on this one? :)

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  andre
                  wrote on last edited by
                  #8

                  For slots to work in a thread, the thread needs a running event loop. That means: exec() must have been called on it (done by default, so a vanilla QThread has one) and the thread must not be stuck in a busy loop.

                  If your thread is doing some huge calculation in one big chunk, and it thus never returns to the event loop, the event that wraps the signal will never be processed, and thus the slot won't be called. It is the same in the main event loop: if you do something very big, or do a busy wait or something like that, events won't be processed anymore, and your application will appear unresponsive to the user.

                  So, if you want to use a signal/slot for an abort, you will need to have a thread that stays responsive and regulary returns to the event loop. Note that you could probably also call processEvents() from within your loop or other time consuming procedure to reach the same effect. Not the nicest solution though.

                  As an alternative, considder creating a normal abort() method, that just sets a flag that you check from your time consuming procedures. Best use a QAtomicInt for such a flag.

                  1 Reply Last reply
                  0
                  • X Offline
                    X Offline
                    xiit
                    wrote on last edited by
                    #9

                    Wow, thanks Andre!

                    So basically I should just add a method to MyWorker (and call it with worker->abort()) and that would work just fine?

                    Just out of curiosity (and because my knowledge is pretty inadequate), why use a QAtomicInt instead of say, a boolean or normal integer as a "flag"?

                    Sorry for my stupidity. :)

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #10

                      The check for the bool flag would be optimized out, as there is no code to change it inside the loop where it is checked over and over again. That doesn't happen with a QAtomicInt.

                      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