需要特别注意的是:
-
线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过quit()退出线程exec()。
QObject派生类对象,将要调用moveToThread,不能指定一个主线程父对象托管内存。
QWidget的对象及派生类对象都只能在GUI主线程运行,不能使用moveToThread移到子线程中,即使没有指定父对象。
多线程对象内存释放
既然QObject对象无法托管内存对象,那么到底是先释放线程对象,还是先释放这个QObject对象?
先把QObject在线程循环中释放(使用QObject::deleteLater函数),然后QThread::quit,然后QThread::wait。
例如:
mywork.h
#ifndef MYWORK_H
#define MYWORK_H
#include <QThread>
#include <QDebug>
class MyWork : public QObject
{
Q_OBJECT
public:
~MyWork() { qDebug() << __FUNCTION__ << endl; }
public slots:
void workSlot()
{
while(1)
{
qDebug() << "Work begin" << endl;
QThread::sleep(5);
qDebug() << "work end" << endl;
}
}
void otherWorkSlot()
{
qDebug() << "otherWork begin" << endl;
QThread::sleep(5);
qDebug() << "otherWork end" << endl;
}
};
#endif // MYWORK_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mywork.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
QThread *_thread;
MyWork * _myWork;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPushButton>
#include "mywork.h"
#include <QThread>
#include <QHBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
_myWork = new MyWork;
_thread = new QThread(this);
_myWork->moveToThread(_thread);
_thread->start();
QPushButton *pb0 = new QPushButton("work", this);
QPushButton *pb1 = new QPushButton("pb", this);
QHBoxLayout *hBox = new QHBoxLayout(this);
hBox->addWidget(pb0);
hBox->addWidget(pb1);
this->setLayout(hBox);
/*发射信号给在另外一个线程的对象的队列中*/
connect(pb0, SIGNAL(clicked()), _myWork, SLOT(workSlot()));
connect(pb1, SIGNAL(clicked()), _myWork, SLOT(otherWorkSlot()));
/*推荐用法释放内存*/
//connect(_thread, SIGNAL(finished()), _myWork, SLOT(deleteLater()));
}
Widget::~Widget()
{
_myWork->deleteLater(); //一定要在QThread线程退出之前
_thread->quit();
_thread->wait();
}
3、Qt线程的同步
多线程在访问同时一个资源,(例如:多个线程可操作的变量、函数等),到底谁来使用这个资源是一个问题,就像一大群人去抢同一块蛋糕,可能其中一个人抢到,更有可能蛋糕被抢个稀烂。在多线程中,这个叫作竞争冒险。那么我们需要定一个规则来约束每一个人,比如:每个人排队来领蛋糕,这个在多线程中叫作同步方法。










