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. [Solved] GUI unresponsive during intensive computation
Forum Updated to NodeBB v4.3 + New Features

[Solved] GUI unresponsive during intensive computation

Scheduled Pinned Locked Moved General and Desktop
11 Posts 4 Posters 4.8k 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.
  • F Offline
    F Offline
    frankiefrank
    wrote on last edited by
    #2

    I don't see how your MainWindow.h code would compile - are you trying to initialize the thread and the updater members there?

    If I understand correctly, you have a worker thread, and you want to notify the main UI thread that it finished work with a certain result? You can emit a signal from that worker thread, and connect that signal to a slot in your main window.

    "Roads? Where we're going, we don't need roads."

    1 Reply Last reply
    0
    • J Offline
      J Offline
      Jyang772
      wrote on last edited by
      #3

      Hi,
      I want to run a member function from MainWindow in a different thread. Is that possible?

      @
      MainWindow::getHash()
      @

      I only included the private member declaration part of MainWindow.h.

      1 Reply Last reply
      0
      • F Offline
        F Offline
        frankiefrank
        wrote on last edited by
        #4

        If you have something happening in a worker thread, can't you pass it all the information so that it does all the work in that thread?

        If getHash() is public, and you pass a pointer to your worker thread so that it can access the MainWindow object, then you can call getHash() and it will be executed in the worker thread. But I think this is really complicating things.

        "Roads? Where we're going, we don't need roads."

        1 Reply Last reply
        0
        • D Offline
          D Offline
          DBoosalis
          wrote on last edited by
          #5

          If you have a long procedure, perhaps executing a for loop, sprinkle some of these in your code

          qApp->processEvents(QEventLoop::ExcludeSocketNotifiers,10);

          This will give the app a few (10 in this case) milliseconds to handle window events

          A better way would be do put rethink your worker thread so it does not block

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Jyang772
            wrote on last edited by
            #6

            Okay, so I copied everything from the MainWindow::getHash() function over to a member function in the worker object. Then I connected a signal/slot and it works.

            However, I would rather just have the function be a member function of MainWindow.

            [quote author="frankiefrank" date="1401064145"]If you have something happening in a worker thread, can't you pass it all the information so that it does all the work in that thread?

            If getHash() is public, and you pass a pointer to your worker thread so that it can access the MainWindow object, then you can call getHash() and it will be executed in the worker thread. But I think this is really complicating things.[/quote]

            How would I pass a pointer to the worker thread?

            1 Reply Last reply
            0
            • F Offline
              F Offline
              frankiefrank
              wrote on last edited by
              #7

              From the code parts you posted I understand you have your Updater object which you move to the worker thread. You can store a pointer to MainWindow as a member of Updater, and set it via the constructor.

              Of course, if you access the same code both in the Main UI thread and in the worker thread - without any thread safety mechanics - you may end up in trouble.

              "Roads? Where we're going, we don't need roads."

              1 Reply Last reply
              0
              • J Offline
                J Offline
                Jyang772
                wrote on last edited by
                #8

                I see.
                So just to be clear, is there no other way of having MainWindow::function() run in a different thread?

                I would either have to pass a pointer to a MainWindow object or just implement MainWindow::function() as a member function of the worker class?

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  frankiefrank
                  wrote on last edited by
                  #9

                  Maybe there are other ways, I can't think of them right now and even these ones may be a bit too complicated for the problem you presented.

                  "Roads? Where we're going, we don't need roads."

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    Jyang772
                    wrote on last edited by
                    #10

                    [quote author="frankiefrank" date="1401090123"]Maybe there are other ways, I can't think of them right now and even these ones may be a bit too complicated for the problem you presented.[/quote]

                    I did some more reading and @Qtconcurrent@ seems to work.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      adolby
                      wrote on last edited by
                      #11

                      I'd recommend separating your business logic/algorithm methods from your GUI classes. This would allow you to follow the object-oriented single responsibility principle better.

                      If you moved your getHash function to a class of your own that inherits from QObject, you will be able to do something like this:

                      @MainWindow::MainWindow(QWidget *parent) :
                      QMainWindow(parent),
                      ui(new Ui::MainWindow)
                      {
                      ui->setupUi(this);
                      ui->textBrowser->setFont(QFont("Monospace",11));
                      ui->textBrowser->setLineWrapMode(QTextEdit::NoWrap);

                      // Make sure not to parent updater, so you can move it to a thread
                      GUIUpdater* updater = new GUIUpdater();
                      QThread* pthread = new QThread(this);
                      
                      updater->moveToThread(pthread);
                      connect(this,SIGNAL(getHash()),updater,SLOT(getHash()));
                      connect(updater,SIGNAL(req()), this, SLOT(getCheckSum()));
                      connect(updater,SIGNAL(Finished()),pthread,SLOT(quit()));
                      connect(pthread, SIGNAL(finished()), updater, SLOT(deleteLater()));
                      

                      }@

                      To call a slot in MainWindow from an updater method, you can use signal and slots like the req() signal you connected in the MainWindow constructor. This will be an asynchronous method call; when you emit the signal from updater, execution will continue in the updater method. The main/GUI thread will have the slot waiting in its event queue.

                      If you need a direct function call, in the case where the timing is important or the doWork method needs a return value from a class on the main/GUI thread (in your case, MainWindow), I would recommend refactoring your doWork method. Make the place where you emit the signal to cause the main/GUI thread to compute be the last line of your doWork method. Then, in the class on the main/GUI thread (MainWindow), your slot will do your computation, and then emit a new signal that will be connected to a new slot containing the rest of the code that was previously in your doWork method after the signal emission.

                      It will look like this:
                      @MainWindow::MainWindow()
                      {
                      connect(worker, SIGNAL(doGUISlot()), this, SLOT(doImportantComputation()));
                      connect(this, SIGNAL(doRestOfWorkSlot()), worker, SLOT(finishWork()));
                      }

                      Class::doWork()
                      {
                      // Do the first part of your work here, then emit to allow GUI to compute. GUI will signal when it's done to
                      // cause finishWork to be executed

                      emit doGUISlot();
                      

                      }

                      MainWindow::doImportantComputation
                      {
                      // Do computation here, then go back to Worker::finishWork

                      emit doRestOfWorkSlot();
                      

                      }

                      Class::finishWork()
                      {
                      // Finish work
                      }@

                      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