Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt signal slot over thread, is this the safe way?

Say, I have 2 threads: A and B, A is the main thread. In thread A, there are two on_button_click slots. The first one is:

on_button_one_clicked(){
  myObject_one = new myObject(this);
  myObject_one->setParent(map);
  myObject_two = new myObject(this);
  myObject_two->setParent(map);
  ...
}

The second one is:

on_button_two_clicked(){
  foreach(myObject* i, map->childItems){
    delete i;
  }
}

Here, myObject and map are all QGraphicsItems. In thread B, a signal is emitted to trigger a slot of thread A:

slot_triggered_by_signal_from_thread_B(){
  foreach(myObject* i, map->childItems){
    i->do_some_thing();
  }
}

Is this safe? Will it happen, when the codes comes to the line i->do_some_thing and meet an empty pointer and crash?

like image 986
Nyaruko Avatar asked Oct 14 '25 12:10

Nyaruko


1 Answers

It is safe as long as you use the auto connection or queued conncetion type between the threads since then the slot will be only invoked when your other slot is finishing up or vice versa. They will not be running "simultaneously". That is the only concern that I could imagine for this not to be safe enough. I believe you meant a scenario like this:

main.cpp

#include <QThread>
#include <QApplication>
#include <QTimer>
#include <QObject>
#include <QPushButton>
#include <QDebug>

class Work : public QObject
{
    Q_OBJECT
    public:
        explicit Work(QObject *parent = Q_NULLPTR) : QObject(parent) { QTimer::singleShot(200, this, SLOT(mySlot())); }
    public slots:
        void mySlot() { emit mySignal(); }
    signals:
        void mySignal();
};

class MyApplication : public QApplication
{
    Q_OBJECT
    public:

    explicit MyApplication(int argc, char **argv)
        : QApplication(argc, argv)
        , pushButton(new QPushButton())
    {
        QStringList stringList{"foo", "bar", "baz"};
        QThread *workerThread = new QThread();

        Work *work = new Work();
        work->moveToThread(workerThread);

        connect(pushButton, &QPushButton::clicked, [&stringList] () {
            for (int i = 0; i < stringList.size(); ++i)
                stringList.removeAt(i);
        });
        connect(work, &Work::mySignal, [&stringList] () {
            for (int i = 0; i < stringList.size(); ++i)
                qDebug() << stringList.at(i);           
        });
    }

    ~MyApplication()
    {
        delete pushButton;
    }

    QPushButton *pushButton;
};

#include "main.moc"

int main(int argc, char **argv)
{
    MyApplication application(argc, argv);   
    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp

Build and Run

qmake && make && ./main
like image 125
lpapp Avatar answered Oct 17 '25 02:10

lpapp