总结使用QObject实现线程
补充一下为什么需要使用继承QObject来实现线程:
原因就是使用继承QThread的类只有run函数是属于新线程的,而其他非run函数依旧属于旧的线程。如果QThread是在ui所在的线程里生成,那么QThread的其他非run函数都是和ui线程一样的,所以,QThread的继承类的其他函数尽量别要有太耗时的操作,要确保所有耗时的操作都在run函数里。在UI线程下调用QThread的非run函数(其实也不应该直接调用run函数,而应该使用start函数),和执行普通函数无区别,这时,如果这个函数要对QThread的某个变量进行变更,而这个变量在run函数里也会被用到,这时就需要注意加锁的问题,因为可能这个变量前几毫秒刚刚在run中调用,再调用时已经被另外的线程修改了。
话不多说,直接上代码,里边有我的注释:
//main.cpp
#include <QtCore/QCoreApplication>
#include "Controller.h"
/*
使用QObject创建线程总结:
1、随便写一个类继承自QObject
2、定义一个工作函数,将耗时的过程写在里边
3、写一个线程管理类,该类至少包含一个QThread和一个你自定义的工作类成员变量
4、在管理类的构造函数中将自定义工作类的对象使用moveToThread()函数移动到QThread对象中,此时该对象的所有东西都是线程对象的了
5、没必要重写run函数,只要在控制类中自定义一个工作信号,并将该工作信号于你自定义的工作函数连接起来,每当发出工作信号,工作函数就开始执行
6、必须在发出工作信号之前执行线程对象的start()函数,否则工作函数无法执行
7、当工作函数中存在while循环时,如果你想手动终止线程中的while循环,那么一定不能使用属于线程的槽函数,因为此时消息队列被线程中的while‘饿死’了。
*/
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Controller control;
control.Start();
return a.exec();
}
//cyx_Worker.h
#pragma once
#include <QObject>
#include <QMutex>
class cyx_Worker :public QObject {
Q_OBJECT
public:
cyx_Worker(QObject* parent = 0);
~cyx_Worker();
void Stop();
public slots:
virtual void slot_doWork();
private:
bool m_bstop;
QMutex m_mutex;
};
//cyx_Worker.cpp
#include "cyx_Worker.h"
#include <QDateTime>
#include <QMutexLocker>
#include <iostream>
using namespace std;
cyx_Worker::cyx_Worker(QObject* parent /* = 0 */) :QObject(parent) {
m_bstop = false;
}
cyx_Worker::~cyx_Worker(){}
void cyx_Worker::slot_doWork() {
qint64 currenttime = QDateTime::currentMSecsSinceEpoch();
int count = 0;
{
QMutexLocker locker(&m_mutex);
m_bstop = false;
}
while (!m_bstop) {
if (QDateTime::currentMSecsSinceEpoch() - currenttime >= 2000) {
currenttime = QDateTime::currentMSecsSinceEpoch();
cout << count << endl;
count++;
}
}
}
void cyx_Worker::Stop() {
cout << "stop!" << endl;
QMutexLocker locker(&m_mutex);
m_bstop = true;
}
//Controller.h
#pragma once
#include <QThread>
#include <QTimer>
#include "cyx_Worker.h"
class Controller :public QObject {
Q_OBJECT
public:
Controller(QObject* parent = 0);
~Controller();
void Start();
signals:
void sig_stop();
void sig_doWork();
public slots:
void slot_stop();
private:
QThread m_workthread;
QTimer* timer;
cyx_Worker* m_worker;
};
//Controller.cpp
#include "Controller.h"
#include <iostream>
using namespace std;
Controller::Controller(QObject* parent /* = 0 */) :QObject(parent) {
m_worker = new cyx_Worker;
timer = new QTimer;
m_worker->moveToThread(&m_workthread);
connect(timer, SIGNAL(timeout()), this, SIGNAL(sig_stop()));
connect(&m_workthread, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
connect(this, SIGNAL(sig_doWork()), m_worker, SLOT(slot_doWork()));
connect(this, SIGNAL(sig_stop()), this, SLOT(slot_stop()));
}
Controller::~Controller() {
m_workthread.quit();
m_workthread.wait(); //m_workthread并没有new出来,所以使用wait等待线程执行结束,如果使用new,则需绑定deleteLater让线程自杀
}
void Controller::Start() {
timer->setSingleShot(true);
timer->start(10000);
m_workthread.start();
emit sig_doWork();
}
void Controller::slot_stop() {
m_worker->Stop();
}
温润如玉,坚毅如铁。