Qt信号槽过线,这是安全的方法吗?

时间:2014-12-06 09:43:42

标签: c++ multithreading qt qtcore qt-signals

说,我有2个线程:A和B,A是主线程。在线程A中,有两个on_button_click槽。第一个是:

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

第二个是:

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

此处, myObject map 都是QGraphicsItem。在线程B中,发出信号以触发线程A的插槽:

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

这样安全吗?当代码到达行 i-> do_some_thing 并遇到空指针并崩溃时会发生吗?

2 个答案:

答案 0 :(得分:2)

只要您在线程之间使用自动连接或排队的conncetion类型就是安全的,因为只有当您的其他插槽完成时才会调用插槽,反之亦然。它们不会“同时”运行。这是我能想象到的唯一一个不足够安全的问题。我相信你的意思是这样的场景:

的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

构建并运行

qmake && make && ./main

答案 1 :(得分:0)

让我们假设主线程在on_button_two_clicked函数中做了一些繁重的工作。 任何其他操作包括用户做某事或来自其他线程的其他请求 (在这种情况下slot_triggered_by_signal_from_thread_B)将被阻止,直到 完成on_button_two_clicked

我认为这意味着它可以保证完成之前的活动。 总之,它是安全的!