UI freezing in multithreaded application



  • 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.


  • Qt Champions 2016

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

    Kind regards.



  • //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();
      }
    
    

  • Qt Champions 2016

    @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!



  • 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.


  • Qt Champions 2016

    @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.


Log in to reply
 

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