Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 475
stamaimer Avatar asked Feb 23 '14 12:02

stamaimer


People also ask

How do slots work Qt?

Slots can be used for receiving signals, but they are also normal member functions. Just as an object does not know if anything receives its signals, a slot does not know if it has any signals connected to it. This ensures that truly independent components can be created with Qt.

Are Qt signals and slots thread-safe?

It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.

Is Qt multithreaded?

Qt offers many classes and functions for working with threads. Below are four different approaches that Qt programmers can use to implement multithreaded applications.

How many signals can be connected to a slot in Qt?

You can have as many signals you want connected to one slot and vice versa. If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.


2 Answers

Unless you create them explicitly, there's no "visible" multi-threading in a Qt program. That means, Qt might use threads internally for e.g. network I/O, but that multithreading is shielded from you and you don't have to care about it. None of your code will be called from other threads, nor will your data be shared with other threads by means that would require you to care about synchronization.

Signal/slot connections come it two main flavors: direct and queued connections:

Direct connections are just function calls that are executed synchronously, with some extra function calls and lookup tables in between. If you emit a signal, all slots are called immediately, before the "emit signal();" returns (as Laszlo's example demonstrates).

Queued connections on the other hand are also executed on the main thread, without any parallelism/multi-threading. However, the slot calls are enqueued in the event loop's event queue: The method doing the emit is completed first, the control returns to the event loop, which then at some later point in time calls the slot(s). The slots are called one after another - the order of execution might not be defined, but they will never be called in parallel.

Now QNetworkAccessManager (QNAM) also works event-driven (*), with queued events: You call get(), the control returns to the event loop; the QNAM sends the request; later, after performing the network I/O, the response is received by QNAM. Think of the network I/O and completion of the response as events, like e.g. mouse clicks: The event occurs, it is put into the event queue, later the event loop calls some internal slot in QNAM, which then triggers finished() to be emitted and mySlot() to be called.

(*) In fact, depending on the platform, QNAM might indeed use multithreading. But that's an implementation detail hidden from the user - so one can stick to the "event-driven" mental model.

like image 180
Frank Osterfeld Avatar answered Sep 17 '22 23:09

Frank Osterfeld


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
like image 42
lpapp Avatar answered Sep 17 '22 23:09

lpapp