c++ - 从不同的 QThread 访问 QObject 方法的安全性

标签 c++ qthread qobject

我正在编写一个应用程序,它使用一个主应用程序线程和第二个线程(并且没有预见到其他线程)。 第二个线程作为“worker”实现,这意味着我没有扩展 QThread 类,而是将我的 worker 对象移动到 Thread。 我们在这里做了一个小例子:

文件:myObject.h

#pragma once
#include <QObject>
#include <worker.h>
class MyObject : public QObject
{
    Q_OBJECT
public:
    MyObject(){}
    void member1();
    void member2();
    Worker* _worker;
};

文件:myObject.cpp

#include "myobject.h"
#include <QThread>
#include <QDebug>
void MyObject::member1()
{
    qDebug() << "MyObject::member1()";
    QThread* _thread = new QThread;
    _worker = new Worker(this);
    _worker->moveToThread(_thread);
    _thread->start();
    _worker->work();
}
void MyObject::member2()
{
    qDebug() << "MyObject::member2()";
}

文件:worker.h

#pragma once
#include <QObject>
class MyObject;
class Worker : public QObject
{
    Q_OBJECT
public:
    Worker(MyObject* myObj) : _myObj(myObj) {}
    void work();
private:
    MyObject* _myObj;
};

文件:myworker.cpp

#include <worker.h>
#include <myobject.h>
#include <QDebug>
void Worker::work()
{
    qDebug() << "Worker::work()";
    _myObj->member2();
}

文件 main.cpp

#include <QCoreApplication>
#include <myobject.h>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyObject myObject;
    myObject.member1();
    return a.exec();
}

Worker::work 直接访问 _myObj->member2(); 是否安全? 如果不是,我应该用信号和插槽机制替换这个调用吗?如果我应该……为什么?

最佳答案

Is it safe to access directly _myObj->member2(); from Worker::work?

很可能不会。这将取决于实现,但一般来说跨线程调用方法很少是安全的。为了确保安全,您需要对从该方法(直接和间接)访问的任何内容应用锁/互斥锁,并确保您从该方法调用的所有内容也是线程安全的。值得庆幸的是,Qt 信号和插槽将其抽象化,因此您无需担心。

If not should I replace this call by signal & slot mechanism?

您应该按照以下方式:

QObject::connect(_thread, &QThread::started, _worker, &MyObject::work);

删除对 MyObject::work() 的直接调用。还要考虑:

QObject::connect(_thread, &QThread::finished, _thread, &QThread::deleteLater);

注意 QObject::connect 是广告安全的。它可以随时从任何线程中的任何对象上的任何线程调用。

If I should... why exactly?

在与您不同的线程中调用对象本质上是危险的。你调用线程安全的方法吗?对于 QObjects,还有一个发送信号和调用槽的额外问题。 work() 会那样做吗?如果在您调用 work() 时线程中的事件循环NOT 正在运行,您的应用将崩溃或至少无法发送信号。通过连接 QThread::startedMyObject::work,您可以确保在运行的线程中正确调用该方法,并以正确的顺序运行事件循环。

为了没有信号和插槽的完整性,您应该这样做以确保它能按预期工作:

if(_thread->isRunning())
    _worker->work();

关于c++ - 从不同的 QThread 访问 QObject 方法的安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50024471/

相关文章:

C++ unicode(或 wstring?)等同于 (char)

c++ - C++中如何判断变量是否在范围内

python - PyQt4 线程正确

c++ - 让 QObject 在执行函数之前等待它的监听器

c++ - 为列表编写合并方法

c++ - 为什么代码打印最后一个 std::cout?

python - PyQt4无法从QThread类调用主Gui类的函数

python - GUI 在循环时变得无响应

python - PyQt5 对象的 SEGV_MAPERR

qt - 获取在应用程序中创建的所有 QObject 的列表