Unsolved 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.
-
@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(); }
-
@zerg2011
Hello,
Is this exactly as it is in your project, or have you removed some things? I'm asking becausem_finder
andm_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 theFinder::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.
-
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 invokeQObject::moveToThread
in the first place.Kind regards.