我正在编写一个使用一个主应用程序线程和第二个线程的应用程序(并且没有预见到其他线程)。 第二个线程实现为“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();
}
从_myObj->member2();
直接访问Worker::work
是否安全?
如果不是,我应该通过信号&amp;更换此呼叫。插槽机制?如果我应该...为什么呢?
答案 0 :(得分:1)
直接访问_myObj-&gt; member2();来自Worker :: work?
很可能不是。它取决于实现,但一般来说,跨线程调用方法很少是安全的。为了使其安全,您需要将锁/互斥锁应用于该方法正在访问的任何内容(直接和间接),并确保从该方法调用的所有内容都是线程安全的。值得庆幸的是Qt信号&amp;插槽抽象,所以你不必担心。
如果不是,我应该通过信号&amp;更换此呼叫。插槽机制?
您应该采取以下方式:
QObject::connect(_thread, &QThread::started, _worker, &MyObject::work);
删除对MyObject::work()
的直接通话。还要考虑:
QObject::connect(_thread, &QThread::finished, _thread, &QThread::deleteLater);
请注意,QObject::connect
是安全的。它可以在任何时候从任何线程中的任何对象上的任何线程调用。
如果我应该......为什么呢?
在与您不同的线程中调用对象本质上是危险的。您调用线程的方法是否安全?对于QObjects
,还有一个问题是发送信号和调用插槽。 work()
这样做吗?如果您在线程中调用work()
事件循环 NOT ,则运行您的应用程序将崩溃或至少无法发送信号。通过连接QThread::started
和MyObject::work
,您可以确保在正在运行的线程中正确调用该方法,并以正确的顺序运行事件循环。
没有信号的完整性&amp;您应该执行此操作以确保它按预期工作:
if(_thread->isRunning())
_worker->work();