c++qtqtcoreqtnetworkqt-signals

does the slot function in Qt run on another thread?


In the following function, manager will emit finished(QNetworkReply*) signal, then the slot function getCategories(QNetworkReply*) will be called.

    void getCategories()
    {
        connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(getCategories(QNetworkReply*)));

        for(int i = 0; i < stores.size(); ++i)
        {
            request.setUrl(QUrl(QString("http://www.example.com/%1").arg(stores[i].store_id)));

            manager.get(request);
        }
    }

If the second signal emitted when the first call of the slot function, does Qt start another thread to run the slot function as the response to the second signal? And if it is so, is there some method to let the second call of slot function wait until the first call is finished?

UPDATE:

I mean is there a possibility that the slot function run in the same time?


Solution

  • It does not start it in a second thread. AFAIK, it will be either a direct call or queued for handling by default. The situation also depends on how you are managing your threads.

    There are several connection types you can choose from, but usually, the default (direct or queued) should be fine.

    I will show you two examples to demonstrate that it also depends on what exactly emits the signal.

    Case 1 (Emitted by the slot being executed)

    main.cpp

    #include <QObject>
    #include <QThread>
    #include <QDebug>
    #include <QCoreApplication>
    
    class MyClass : public QObject
    {
        Q_OBJECT
    
        public:
            explicit MyClass(QObject *parent = 0) : QObject(parent), counter(0)
            {
                connect(this, SIGNAL(mySignal()),
                        this, SLOT(mySlot()), Qt::QueuedConnection);
            }
    
        signals:
            void mySignal();
        public slots:
            void mySlot()
            {
                if (counter >= 2) return;
                ++counter;
                qDebug() << "mySlot started";
                emit mySignal();
                QThread::msleep(1000);
                qDebug() << "mySlot quit";
            }
    
        private:
            int counter;
    
    };
    
    #include "main.moc"
    
    int main(int argc, char **argv)
    {
        QCoreApplication application(argc, argv);
        MyClass myObject;
        myObject.mySlot();
        return application.exec();
    }
    

    main.pro

    TEMPLATE = app
    TARGET = test
    QT = core
    SOURCES += main.cpp
    

    Build and Run

    moc -o main.moc main.cpp && qmake && make && ./test
    

    Output

    mySlot started 
    mySlot quit 
    mySlot started 
    mySlot quit
    

    You would get the following output without queued connection to indicate that it would be a direct call in the middle of the slot execution in my example:

    mySlot started
    mySlot started
    mySlot quit  
    mySlot quit
    

    Case 2 (not emitted by the slot being executed)

    main.cpp

    #include <QObject>
    #include <QThread>
    #include <QDebug>
    #include <QCoreApplication>
    #include <QTimer>
    
    class MyClass : public QObject
    {
        Q_OBJECT
    
        public:
            explicit MyClass(QObject *parent = 0) : QObject(parent), counter(0), timer(new QTimer(this))
            {
                // Note: there is no need for queued connection in this case
                connect(this, SIGNAL(mySignal()), this, SLOT(mySlot()));
                connect(timer, SIGNAL(timeout()), this, SLOT(mySlot()));
                timer->setSingleShot(true);
                timer->start(200);
            }
    
        signals:
            void mySignal();
        public slots:
            void mySlot()
            {
                ++counter;
                qDebug() << "mySlot started" << counter;
                QThread::msleep(1000);
                qDebug() << "mySlot quit" << counter;
            }
    
        private:
            int counter;
            QTimer *timer;
    
    };
    
    #include "main.moc"
    
    int main(int argc, char **argv)
    {
        QCoreApplication application(argc, argv);
        MyClass myObject;
        myObject.mySlot();
        return application.exec();
    }
    

    main.pro

    TEMPLATE = app
    TARGET = test
    QT = core
    SOURCES += main.cpp
    

    Build and Run

    moc -o main.moc main.cpp && qmake && make && ./test
    

    Output

    mySlot started 1 
    mySlot quit 1 
    mySlot started 2 
    mySlot quit 2