Results 1 to 5 of 5

Thread: GUI freezes in loop: Thread does not help?

  1. #1
    Join Date
    Nov 2010
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Question GUI freezes in loop: Thread does not help?

    Hello everybody,

    I'm quite new to Qt, but I'm going to start to love it. Unfortunately I have a problem I could not solve by myself, even not after some days of thinking and experiments. So it would be very nice if someone could help me with expert knowledge, please.

    My scenario:
    I have a loop in which I am calculating some stuff. When the user presses a button to start it the GUI freezes until the loop is done. In many forums they say "please use qApp->processEvents()" and it will be fine.

    But:
    When I do not use "qApp->processEvents()" the loop takes about 2 or 3 secs. With "qApp->processEvents()" it takes about 1 minute!! (if I call "qApp->processEvents()" in every loop step). When I use "qApp->processEvents()" only every 100.000 step the GUI starts to "stutter" again.

    My dream:
    The user presses a button. The loop begins to solve the problem, ends after the 2 or 3 seconds. During the loop calculation the user can continue to use the GUI without any "stuttering".

    My example code:
    The user can press button A to increment an int-value, lets say "a". Two other buttons start a loop in which another int-value - say b - is incremented. When the user starts the "b-loop" it is not possible to press Button A until the "b-loop" is done. This is not what I want.
    A solution without a thread and with a thread is included (the "two buttons"). Both do not behave as I would like it.

    I am very thankful for any help!

    Regards
    Matty23

    Qt Code:
    1. #include <QThread>
    2.  
    3. #include "qt_thread.h"
    4.  
    5. int a = 0;
    6. int b = 0;
    7.  
    8. Qt_Thread *q;
    9.  
    10. class MyThread : public QThread
    11. {
    12. public:
    13. void run();
    14. };
    15.  
    16. void MyThread::run()
    17. {
    18. b = 0;
    19.  
    20. while (b < 1000000){
    21. b++;
    22. q->setb(b);
    23.  
    24. //qApp->processEvents();
    25. }
    26. exec();
    27. }
    28.  
    29.  
    30.  
    31. Qt_Thread::Qt_Thread(QWidget *parent)
    32. : QWidget(parent)
    33. {
    34. ui.setupUi(this);
    35.  
    36. q = this;
    37.  
    38. connect(ui.pbIncA, SIGNAL(clicked()), this, SLOT(pbIncAClicked()));
    39. connect(ui.pbWithoutThread, SIGNAL(clicked()), this, SLOT(pbWithoutThreadClicked()));
    40. connect(ui.pbWithThread, SIGNAL(clicked()), this, SLOT(pbWithThreadClicked()));
    41. }
    42.  
    43.  
    44.  
    45. void Qt_Thread::pbWithoutThreadClicked()
    46. {
    47. b = 0;
    48.  
    49. while (b < 1000000){
    50. b++;
    51. ui.lbb->setText( QString("%1").arg(b) );
    52. }
    53. }
    54.  
    55. void Qt_Thread::pbWithThreadClicked()
    56. {
    57. MyThread m;
    58. m.run();
    59. }
    60.  
    61. void Qt_Thread::setb(int b)
    62. {
    63. ui.lbb->setText( QString("%1").arg(b) );
    64. }
    65.  
    66. void Qt_Thread::pbIncAClicked()
    67. {
    68. a++;
    69. ui.lba->setText( QString("%1").arg(a) );
    70. }
    71.  
    72.  
    73. Qt_Thread::~Qt_Thread()
    74. {
    75.  
    76. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: GUI freezes in loop: Thread does not help?

    Hi,

    Best approach to solve this problem, is:
    1. create QObject which do calculation in some slot:
    Qt Code:
    1. class MyCalulations : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. MyCalulations(QObject* parent);
    7.  
    8. public slots:
    9. void doHeavyCalculation();
    10.  
    11. signals:
    12. void calculationCompleted();
    13. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. MyCalulations::MyCalulationsQObject* parent) :
    2. QObject(parent)
    3. {}
    4.  
    5. void MyCalulations::doHeavyCalculation()
    6. {
    7. // do some have calculation code here:
    8. .....
    9.  
    10.  
    11. emit calculationCompleted(); // report end of calculation
    12. }
    To copy to clipboard, switch view to plain text mode 

    2. Then in your widget/main window:
    Qt Code:
    1. MyWidget::MyWidget(QWidget* parent) :
    2. QWidget(parent)
    3. {
    4. ui->constuct_ui();
    5.  
    6. QThread* thread = new QThread(this);
    7. MyCalulations* calc = new MyCalulations(this);
    8. calc->moveToThread(thread);
    9.  
    10. connect(ui->buttonCalc, SIGNAL(click()),
    11. calc, SLOT(doHeavyCalculation()));
    12. connect(calc, SIGNAL(calculationCompleted()),
    13. this, SLOT(doSomethingWhenItIsDone()));
    14. }
    To copy to clipboard, switch view to plain text mode 

    So as you can see it is easy and Qt will do lots of stuff for you.

  3. #3
    Join Date
    Apr 2010
    Posts
    769
    Thanks
    1
    Thanked 94 Times in 86 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: GUI freezes in loop: Thread does not help?

    processEvents() is fairly slow. You only need to call it often enough to keep your GUI responsive; calling it on every loop iteration adds a lot of unnecessary calls. Something like

    Qt Code:
    1. if ( !(loopIter % 10000) )
    2. processEvents();
    To copy to clipboard, switch view to plain text mode 

    will likely work. Adjust the divisor as required to maintain interactivity.

    Spawning the work performed within the loop in a thread is another option, as you note, but I'd try the approach outlined here first because it's simple. If it doesn't work, then you'll have to explore threading. Note that you can't directly updated the GUI from within a thread; you'll need to work out some sort of signalling mechanism if GUI updates are required.

  4. #4
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: GUI freezes in loop: Thread does not help?

    You really need to learn how threads work. Your subclassing QThread (which isn't necessary in this case), creating a method called 'run' and then calling that function. So it's just acting like any another class. Instead of calling run() try calling start(). You may also need to use moveToThread() to ensure your slots get called in the current thread (otherwise they'll be called in your main thread)

    Also, don't do UI calls in a thread. That's just asking for trouble. Do all UI in your main thread.

    Nokia has a fantastic archive of presentation material. Maybe you would find it beneficial to watch the Threading in Qt video/presentation.

  5. #5
    Join Date
    Nov 2010
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GUI freezes in loop: Thread does not help?

    Thanks for all your help. I am very new to this chapter and it seems like I have to learn a lot about it.

    My modified source seems to work quite well and it looks like this:
    Qt Code:
    1. #include <QThread>
    2. #include <QMessageBox>
    3. #include "qt_thread.h"
    4.  
    5. int a = 0;
    6. int b = 0;
    7.  
    8. MyCalc *c;
    9.  
    10.  
    11.  
    12.  
    13.  
    14. MyCalc::MyCalc(QObject* parent) :
    15. QObject(parent)
    16. {
    17.  
    18. }
    19.  
    20. void MyCalc::myLoop()
    21. {
    22. b = 0;
    23. float tmp = 0.0;
    24.  
    25.  
    26. while (b < 300000000){
    27. tmp = 6.5192412518215212 * (tmp+1) / 2.6315211121893 + b * b;
    28.  
    29. b++;
    30.  
    31. if (! (b % 100000000) ){
    32. emit incrementedB();
    33. }
    34. tmp = 0.0;
    35.  
    36. }
    37.  
    38. emit finishedLoop(); // report end of calculation
    39. }
    40.  
    41.  
    42.  
    43. void Qt_Thread::updateMyB()
    44. {
    45. ui.lbb->setText( QString("%1").arg(b) );
    46. }
    47.  
    48.  
    49.  
    50. Qt_Thread::Qt_Thread(QWidget *parent)
    51. : QWidget(parent)
    52. {
    53. ui.setupUi(this);
    54.  
    55. t = new QThread();
    56. t->start();
    57.  
    58. c = new MyCalc();
    59. c->moveToThread(t);
    60.  
    61. connect(ui.pbWithThread, SIGNAL(clicked()), c, SLOT(myLoop()));
    62. connect(c, SIGNAL(finishedLoop()),this, SLOT(afterLoop()));
    63. connect(c, SIGNAL(incrementedB()), this, SLOT(updateMyB()) );
    64.  
    65.  
    66. connect(ui.pbIncA, SIGNAL(clicked()), this, SLOT(pbIncAClicked()));
    67. connect(ui.pbWithoutThread, SIGNAL(clicked()), this, SLOT(pbWithoutThreadClicked()));
    68. }
    69.  
    70.  
    71.  
    72. void Qt_Thread::pbWithoutThreadClicked()
    73. {
    74. b = 0;
    75. float tmp = 0.0;
    76.  
    77. while (b < 300000000){
    78. tmp = 6.5192412518215212 * (tmp+1) / 2.6315211121893 + b * b;
    79. b++;
    80. if (! (b % 100000000) ){
    81. ui.lbb->setText( QString("%1").arg(b) );
    82. qApp->processEvents();
    83. }
    84. tmp = 0.0;
    85.  
    86. }
    87.  
    88. ui.lbb->setText( "Fertig :)" );
    89. }
    90.  
    91. void Qt_Thread::pbWithThreadClicked()
    92. {
    93.  
    94. }
    95.  
    96. void Qt_Thread::setb(const int b)
    97. {
    98. ui.lbb->setText( QString("%1").arg(b) );
    99. }
    100.  
    101. void Qt_Thread::pbIncAClicked()
    102. {
    103. a++;
    104. ui.lba->setText( QString("%1").arg(a) );
    105. }
    106.  
    107. void Qt_Thread::afterLoop()
    108. {
    109. ui.lbb->setText("Fertig! :)");
    110. }
    111.  
    112.  
    113. Qt_Thread::~Qt_Thread()
    114. {
    115.  
    116. }
    To copy to clipboard, switch view to plain text mode 

    Thank you all!

Similar Threads

  1. GUI Freezes unless there's incoming data
    By crisp in forum Qt Programming
    Replies: 17
    Last Post: 7th February 2009, 18:56
  2. Keyboards freezes
    By giusepped in forum Qt-based Software
    Replies: 0
    Last Post: 28th October 2008, 02:30
  3. Replies: 4
    Last Post: 26th June 2008, 19:41
  4. Main Thread Event loop
    By ^NyAw^ in forum Qt Programming
    Replies: 1
    Last Post: 20th March 2007, 13:10
  5. My SDI application freezes when it is inactive ...why ?
    By yellowmat in forum Qt Programming
    Replies: 1
    Last Post: 5th September 2006, 17:37

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.