You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Wednesday, November 2nd 2011, 4:49pm

Thread blocks GUI after emit, even if Qt::QueuedConnection is used

Hi guys,

I guess its a simple problem, but I cannot get rid of it. I try to invoke a function in a thread asynchronously. So I am using the signal-slot functionality of Qt. However, the thread blocks somehow the GUI. Strangely my GUI freezes after the signal was emitted. Even more strange is for me that a qDebug() is still executed. I made a simple showcase and attached it exemplifying the case.

It just consists of a QThread derived class testThread. The mainwindow has a private variable of testThread called tt. The code below is the mainwindow.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ 
ui->setupUi(this); 
QObject::connect(this, SIGNAL(invokeLoop()), &tt, SLOT(startLoop()), Qt::QueuedConnection); 
}

MainWindow::~MainWindow(){ delete ui;} 



// button in GUI is pressed
void MainWindow::on_pushButton_released(){ 
emit invokeLoop(); qDebug() << "test";
}



Source code

1
2
3
4
5
6
7
8
9
// testthread.cpp
#include "testthread.h"
testThread::testThread(QObject *parent) : QThread(parent){} 


// to infinity and beyond
void testThread::startLoop(){ 
for (int i = 0; ; ++i){ --i; }
}



I am sorry if this is a too common problem, but I could not find a solution, since everywhere they say, use Qt::QueuedConnection....

Thanks!

edit:

sorry if forgot to start the thread in the code above and in the example. but changing the code to:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ 
ui->setupUi(this); 
tt.start(); 
QObject::connect(this, SIGNAL(invokeLoop()), &tt, SLOT(startLoop()), Qt::QueuedConnection);
}

MainWindow::~MainWindow(){ delete ui;}

void MainWindow::on_pushButton_released(){ 
emit invokeLoop(); qDebug() << "test";
}




Does not help
NothingSpecial has attached the following file:
  • threadProbs.zip (10.01 kB - 6 times downloaded - latest: May 2nd 2014, 4:23pm)

This post has been edited 2 times, last edit by "NothingSpecial" (Nov 2nd 2011, 4:56pm)


Junior

Professional

  • "Junior" is 53 years old today
  • "Junior" is male

Posts: 1,622

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

2

Wednesday, November 2nd 2011, 6:38pm

QThread contains a virtual function run() which is used to start the event loop for the thread. Or you can create an event loop with exec(), otherwise the thread doesn't use one and thus the application will freeze until the thread is complete. In your case you have a forever loop so that will never happen.

Following is what I used to test with, it might help:

testThread.h

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef TESTTHREAD_H
#define TESTTHREAD_H

#include <QThread>

class testThread : public QThread
{
    Q_OBJECT
    public:
        explicit testThread(QObject *parent = 0);
        void run();

    public slots:
        void halt();

    private:
        int i;
};

#endif // TESTTHREAD_H


testThread.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <QtCore/QDebug>
#include "testthread.h"

testThread::testThread(QObject *parent) :
    QThread(parent)
{
}

void testThread::run()
{
    i=1;
    forever {
        if( i ==0 )
            break;

        qDebug() << "thread loop " << i++; sleep(1);
    }
}

void testThread::halt()
{
    i=0;
}


mainwindow.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <QtCore/QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_released()
{
    if( tt.isRunning() ){
        qDebug() << "halt called on thread.";
        tt.halt();
    } else {
        qDebug() << "starting thread...";
        tt.start();
    }
}

3

Wednesday, November 2nd 2011, 7:04pm

the op needs to rtfm on QThread. You must put your code you want to be run in the thread inside a virtual method called run. To make the code be executed in a DIFFERENT thread (ie different to the calling thread), you must call start() on the thread.

Since you have done none of this, and your 'thread' is actually just an object in the gui thread, of course it will block...


Junior: run() does not start an event loop, exec() does. Not having an event loop in a QThread will not freeze the app. It merely means that any objects in the new thread will not have any slots called from signals.
If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

This post has been edited 1 times, last edit by "Amleto" (Nov 2nd 2011, 7:10pm)


Junior

Professional

  • "Junior" is 53 years old today
  • "Junior" is male

Posts: 1,622

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

4

Wednesday, November 2nd 2011, 7:29pm

I guess I was a little off paraphrasing from the documentation "QThreads begin executing in run(). By default, run() starts the event loop by calling exec()...".

5

Wednesday, November 2nd 2011, 7:30pm

alright, so I have to put everything in run(), I hoped to be able to avoid that. Thanks

6

Friday, November 4th 2011, 5:34pm

alright, so I have to put everything in run(), I hoped to be able to avoid that. Thanks


you had everything in a slot. So what is the difference?
If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.