1、QThread类介绍
The QThread class provides a platform-independent way to manage threads.
Thread类提供了与平台无关的方式来管理线程。
A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.
一个QThread对象管理一个控制线程。该控制线程执行入口是run()函数。
缺省情况下,run()函数内部只是仅仅调用exec()函数,来开启一个事件循环。当然,我们也可以重写run()函数,来实现高级的线程功能。当run()函数结束时,该控制线程也就结束了。
2、使用QObject::moveToThread来实现多线程
controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork();
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
explicit Controller(QObject *parent = 0);
~Controller();
signals:
void operate();
public slots:
};
#endif // CONTROLLER_H
controller.cpp
#include "controller.h"
#include <QThread>
#include <QDebug>
#include <unistd.h>
void Worker::doWork()
{
//模拟干活
while(1)
{
qDebug() << "doWork in thread " << thread()->currentThreadId();
sleep(1);
}
}
Controller::Controller(QObject *parent) : QObject(parent)
{
Worker *worker = new Worker;
worker->moveToThread(&workerThread);//worker的槽函数将在workerThread线程执行
connect(this, SIGNAL(operate()), worker, SLOT(doWork()));
connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
workerThread.start();
emit operate();
}
Controller::~Controller()
{
workerThread.quit();//终止事件循环,则线程退出
workerThread.wait();
}
main.cpp
#include "controller.h"
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
Controller c1;
return app.exec();
}
3、通过继承QThread类,并重写run函数,来实现多线程
controller.h
#ifndef _CONTROLLER
#define _CONTROLLER
#include <QThread>
class WorkerThread : public QThread
{
Q_OBJECT
public:
WorkerThread(bool &bExited,QObject *parent=0);
~WorkerThread();
void run();
private:
const bool &m_bExited;
};
class Controller : public QObject
{
Q_OBJECT
public:
Controller(QObject *parent=0);
void startWorkInAThread();
void stopWork();
private:
bool m_bExited;
WorkerThread *m_thread;
};
#endif
controller.cpp
#include "controller.h"
#include <unistd.h>
#include <QDebug>
WorkerThread::WorkerThread(bool &bExited,QObject *parent)
:m_bExited(bExited),QThread(parent)
{
}
WorkerThread::~WorkerThread()
{
qDebug() << "WorkerThread::~WorkerThread() was called";
}
//run函数结束,则线程退出
void WorkerThread::run()
{
while(!m_bExited)
{
sleep(1);
qDebug() << "in WorkerThread::run(), thread = " << currentThreadId();
}
}
Controller::Controller(QObject *parent):QObject(parent)
{
m_bExited=false;
}
void Controller::startWorkInAThread()
{
m_thread=new WorkerThread(m_bExited);
connect(m_thread,SIGNAL(finished()),m_thread,SLOT(deleteLater()));
m_thread->start();
}
void Controller::stopWork()
{
m_bExited=true;
m_thread->wait();
}
main.cpp
#include "controller.h"
#include <QCoreApplication>
#include <unistd.h>
int main(int argc,char *argv[])
{
QCoreApplication app(argc,argv);
Controller c;
c.startWorkInAThread();
//模拟其他工作
sleep(5);
c.stopWork();
return app.exec();
}
4、对于子类化QThread,需要注意的点
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.
When subclassing QThread, keep in mind that the constructor executes in the old thread while run() executes in the new thread. If a member variable is accessed from both functions, then the variable is accessed from two different threads. Check that it is safe to do so.