我以一种与我习惯看到的非常不同的方式使用 QThread。 看看:
#include <QObject>
#include <QThread>
class CustomWorker : public QObject
{
Q_OBJECT
public:
CustomWorker()
{
_thread = new QThread();
this->moveToThread(_thread);
_thread->start();
connect(_thread, SIGNAL(finished()), this, SLOT(threadFinished()));
connect(this, SIGNAL(process1Signal()), this, SLOT(process1Slot()));
connect(this, SIGNAL(process2Signal()), this, SLOT(process2Slot()));
}
void deleteMe()
{
_thread->quit();
}
public:
void process1(){ emit process1Signal(); }
void process2(){ emit process2Signal(); }
signals:
void process1Signal();
void process2Signal();
private slots:
void process1Slot(){ /* code to run in background */ }
void process2Slot(){ /* code to run in background */ }
void threadFinished()
{
_thread->deleteLater();
this->deleteLater();
}
private:
QThread* _thread;
};
因此,我可以使用 CustomWorker 直接调用函数 process1() 或 process2() :
_worker = new CustomWorker;
connect(_worker, SIGNAL(process1Ended()), this, SLOT(handleProcess1()));
connect(_worker, SIGNAL(process2Ended()), this, SLOT(handleProcess2()));
...
_worker->process1();
工作正常...但删除部分有时会崩溃:
_worker->deleteMe();
我不知道发生了什么。正确的实施方法是什么?
PS:我使用宏来创建信号和槽,所以我不会输入太多这样的内容。
我认为问题在于您可能会在线程完成之前删除它。因此,请更改您的
deleteMe()
方法,如下所示:
void deleteMe()
{
_thread->quit();
_thread->wait(); // just add this line
}
并且不建议删除类内的对象。
你的问题是线程亲和性;对象正在哪个线程运行。请注意,
QThread
实际上并不是一个线程,而更像是一个线程控制器。
class CustomWorker : public QObject
{
public:
CustomWorker()
{
_thread = new QThread();
this->moveToThread(_thread);
}
private:
QThread* _thread
};
_worker = new CustomWorker;
假设一个
CustomWorker
对象在主(gui)线程上实例化。它的构造函数创建 QThread
成员实例,该实例也在主线程上。
在调用
moveToThread(_thread)
之后,_worker
对象现已移至新线程。线程实例 _thread
不是 CustomWorker
类的子级,因此它保留在主线程上。当调用删除时,您现在尝试删除 QThread
对象,该对象与您要删除的对象驻留在不同的线程上。
要解决此问题,请将 QThread 从 CustomerWorker 类中移出。线程与在其上运行的对象唯一的关联是通过 moveToThread 函数。
考虑您的设计应该允许一个 QThread 对象和多个可以在该线程上运行的工作实例。
有关
QThread
的更多信息,我建议阅读这篇博文。
在很多情况下,Qt 的
QThread
类需要 deleteLater()
而不是 delete
来拥有 QObject,否则会崩溃。
即使您
delete
QThread
本身也是如此:因此它应该是 myThreadPtr->deleteLater()
。
基本上,即使
QThread
尚未运行,也应将其视为正在运行。