线程
线程中无法使用任何界面部件类,所以界面与线程之间的协作通过信号和槽或者其他通信机制。
1、线程类
QThread类
2、相关信号
[signal] void QThread::finished() //线程终止结束时发出的信号
[signal] void QThread::started() //线程开始运行发出的信号
3、相关槽
[slot] void QThread::quit() //线程退出
[slot] void QThread::start(Priority priority = InheritPriority) //线程启动函数
[slot] void QThread::terminate()
//终止线程的运行,可能立马终止,也可能延迟终止,时间不确定,取决于操作系统的调度机制。
//可以使用QThread::wait()来确保线程退出,一般情况最好不要用这个函数
4、常用方法
4.1 线程阻塞
bool QThread::wait(unsigned long time = ULONG_MAX) //阻塞线程,类似POSIX中的pthread_join()
4.2 线程退出
void QThread::exit(int returnCode = 0) //线程退出
4.3 线程睡眠延时
[static] void QThread::msleep(unsigned long msecs)
[static] void QThread::sleep(unsigned long secs)
[static] void QThread::usleep(unsigned long usecs)
4.4 进入事件循环
[protected] int QThread::exec()
5、线程的状态
bool QThread::isFinished() const //判断线程是否终止
bool QThread::isRunning() const //线程是否是运行状态
6、获取线程ID
6.1 获取线程相对应的对象
[static] QThread *QThread::currentThread()
6.2 获取当前线程的句柄
[static] Qt::HANDLE QThread::currentThreadId()
7、设置/获取线程参数
常用设置参数方法,一般用默认即可。
7.1 设置/获取线程优先级
void QThread::setPriority(Priority priority)
Priority QThread::priority() const
7.2 设置/获取线程栈大小
void QThread::setStackSize(uint stackSize)
uint stackSize() const
8、线程入口函数
[virtual protected] void QThread::run()
//虚保护函数,由用户重写
9、线程同步
9.1 互斥锁
QMutex类
9.2 读写锁
QReadWriteLock 类
允许多进程读,不可以多进程写
9.3 信号量
QSemaphore类
9.4 条件变量
QWaitContion类
参考Qt提供的示例 Wait Conditions Example
QThread简单使用
#include <QMainWindow>
#include <QProcess>
#include <QThread>
namespace Ui {
class MainWindow;
}
class TestThread;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
TestThread *myTestThread;
};
class TestThread : public QThread
{
protected:
virtual void run();
public:
TestThread();
void startThread();
void stopThread();
private:
bool threadStatus;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myTestThread = new TestThread;
connect(ui->pushButton_2, &QPushButton::clicked, this->myTestThread, &TestThread::startThread);
connect(ui->pushButton_3, &QPushButton::clicked, this->myTestThread, &TestThread::stopThread);
}
void TestThread::run()
{
static int cnt = 0;
while (threadStatus)
{
qDebug() << "thread is running" << cnt++;
this->sleep(1);
}
}
TestThread::TestThread()
{
this->threadStatus = 0; //线程还没运行
}
void TestThread::startThread()
{
this->threadStatus = 1;
this->start();
}
void TestThread::stopThread()
{
this->threadStatus = 0;
this->quit();
}
参考手册还提供了一种特别创建线程的方法:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
worker->moveToThread(&workerThread);
使得worker类中的槽doWork
得以在线程中执行。使用这种方式很方便将一些耗时的工作丢给单独的工作线程来做,不同线程之间通过信号和槽进行关联协作。