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. UI freezing in multithreaded application
Forum Updated to NodeBB v4.3 + New Features

UI freezing in multithreaded application

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 1.4k 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.
  • Z Offline
    Z Offline
    zerg2011
    wrote on last edited by
    #1

    Hi

    I'm developing desktop application that has heavy time consuming function - searching in text.

    This function was moved to parallel thread to avoid UI ( and obviously main event loop ) freezing.
    However this technique didn't solve problem with UI freezing.

    I see that my form doesn't respond to mouse actions, and doesn't repaint itself, until the search completed. I see in ps that not only thread that performs searching but also main thread shows CPU time consuming around 100% . When the search finishes UI freezing ends, too.

    My question is - how can i discover the reason of UI freezing, and specifically that fragment of code which cause UI freezing?

    I tried to use callgrind but he only shows that most time consuming actions are inside QApplication.

    1 Reply Last reply
    0
    • kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

      @zerg2011
      Hello,
      You're (most probably) blocking the main event loop somewhere. Do you mind sharing how you set up your threading?

      Kind regards.

      Read and abide by the Qt Code of Conduct

      Z 1 Reply Last reply
      0
      • kshegunovK kshegunov

        @zerg2011
        Hello,
        You're (most probably) blocking the main event loop somewhere. Do you mind sharing how you set up your threading?

        Kind regards.

        Z Offline
        Z Offline
        zerg2011
        wrote on last edited by
        #3
        //your code here
          class Finder : public QObject
          {
              Q_OBJECT
        
          public:
              Finder( Form* form );
        
          public slots:
              void find();
        
          private:
              Form* m_form;
          };
        
          void Finder::find()
          {
              foreach( const QString & s, m_form->m_text ) {
                  if ( s == "pattern" ) {
                      ++(m_form->m_counter);
                  }
              }
          }
        
          class Form : public QDialog
          {
          Q_OBJECT
          public:
              Form(QWidget* parent = 0);
        
              QVector<QString> m_text;
              int m_counter;
        
          private:
              QPushButton *m_findButton;
        
              Finder *m_finder;
              QThread m_finderThread;
          };
        
          Form::Form(QWidget* parent)
              :QDialog(parent)
          {
              connect(m_findButton, SIGNAL(clicked(bool)), m_finder,  SLOT(find()));
        
              m_finder->moveToThread(&m_finderThread);
              connect(&m_finderThread, SIGNAL(finished()), m_finder, SLOT(deleteLater()));
              m_finderThread.start();
          }
        
        
        kshegunovK 1 Reply Last reply
        0
        • Z zerg2011
          //your code here
            class Finder : public QObject
            {
                Q_OBJECT
          
            public:
                Finder( Form* form );
          
            public slots:
                void find();
          
            private:
                Form* m_form;
            };
          
            void Finder::find()
            {
                foreach( const QString & s, m_form->m_text ) {
                    if ( s == "pattern" ) {
                        ++(m_form->m_counter);
                    }
                }
            }
          
            class Form : public QDialog
            {
            Q_OBJECT
            public:
                Form(QWidget* parent = 0);
          
                QVector<QString> m_text;
                int m_counter;
          
            private:
                QPushButton *m_findButton;
          
                Finder *m_finder;
                QThread m_finderThread;
            };
          
            Form::Form(QWidget* parent)
                :QDialog(parent)
            {
                connect(m_findButton, SIGNAL(clicked(bool)), m_finder,  SLOT(find()));
          
                m_finder->moveToThread(&m_finderThread);
                connect(&m_finderThread, SIGNAL(finished()), m_finder, SLOT(deleteLater()));
                m_finderThread.start();
            }
          
          
          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by kshegunov
          #4

          @zerg2011
          Hello,
          Is this exactly as it is in your project, or have you removed some things? I'm asking because m_finder and m_findButton don't seem to be initialized. Additionally, this line:

           foreach( const QString & s, m_form->m_text )
          

          on first glance reads as a race condition. If in the main thread someone changes the variable and you're reading it at the same time you're going to be in a lot of trouble finding out why you get inconsistent results (or crashes). You could remap the QPushButton::clicked signal to connect to the Finder::find slot with a string argument by means of QSignalMapper.

          Kind regards.

          ADDENDUM:
          This ++(m_form->m_counter) is also potentially a race condition!

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • Z Offline
            Z Offline
            zerg2011
            wrote on last edited by
            #5

            Yes, I simplify code from my project, I skip initialisation.
            I agree with you about race condition. Threads synchronisation is separate problem.
            My current concern is about main event loop freezing.

            Frankly, while I was typing code example, it has just downed upon me, that probably, although
            m_finder lives not in main thread , find() works synchronously with main event loop.

            I mean that main event loop can not go on while find() does not finish.

            kshegunovK 1 Reply Last reply
            0
            • Z zerg2011

              Yes, I simplify code from my project, I skip initialisation.
              I agree with you about race condition. Threads synchronisation is separate problem.
              My current concern is about main event loop freezing.

              Frankly, while I was typing code example, it has just downed upon me, that probably, although
              m_finder lives not in main thread , find() works synchronously with main event loop.

              I mean that main event loop can not go on while find() does not finish.

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              @zerg2011

              I agree with you about race condition. Threads synchronisation is separate problem.
              My current concern is about main event loop freezing.

              It is not. And you shouldn't need explicit synchronization when using signal-slots, that's one of the main reasons they're preferred.

              Frankly, while I was typing code example, it has just downed upon me, that probably, although
              m_finder lives not in main thread , find() works synchronously with main event loop.

              Nope, the slot is executed in the thread the QObject lives in, that's why you invoke QObject::moveToThread in the first place.

              Kind regards.

              Read and abide by the Qt Code of Conduct

              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