0、说明

QThread提供了一种与平台无关的线程管理方法。

一个QThread对象管理一个线程。QThread通过run()方法启动线程。默认情况下,run()方法通过exec()启动一个事件循环,并且在线程中运行这个时间循环。

我们可以通过调用QObject::moveToThread()来把某项事务转移到Thread中,下面以一个Worker类为例:

class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(QString parameter){
QString result;
/*... 在此处填写比较重要、需要阻塞的操作 ...*/
emit resultReady(result);
} signals:
void resultReady(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.wair();
}
public slots:
void handleResults(QString);
signals:
void operate(QString);
};

在Worker类的槽函数中的代码将在另一个Thread中执行。不过,我们可以自由地在任何线程中,连接Worker的槽到任何对象的任何信号中。在不同的线程中连接信号与槽是安全的,因为才采用了队列连接的机制。

另一种使代码运行在不同的线程中的方法是,构造QThread子类,覆写run()方法,例如:

class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/*...在这里写一些代价高昂且需要阻塞的操作...*/
emit resultReady(result);
}
signals:
void resultReady(QString);
}; void MyObject :: startWorkInAThread()
{
WorkerThread * workerThread = new WorkerThread(this);
connect(workerThread,&WorkerThread::resultReady,this,&MyObject::handleResults);
connect(workerThread,&WorkerThread::finished,workerThread,&QObject::deleteLater);
workerThread->start();
}

在本例中,线程在run()函数结束后就会退出。除非调用exec(),否则在该线程中就不会存在任何事件循环。

一个QThread对象是生存在初始化它的老线程中的,并不是存在于调用run()的新线程中,这意味着QThread的全部队列槽和调用方法都会在老线程中执行。因此,开发者如果想在新线程中调用槽函数,必须使用worker-object方法,这个槽函数不能直接在该QThread子类中实现。

不同于队列槽和调用的方法,直接在QThread中执行的方法将会在该线程中运行。当实现一个QThread子类时,在新线程中调用run()方法,但是是在老线程中构造该新线程。如果一个成员变量被多个函数调用,那么实际上该变量是被多个线程访问的,这一过程是安全的。

注意

不同线程间的Object进行交流时,要特别小心。通常情况下,函数调用应该在创建QThread的线程中进行(例如setPriority()),除非有文件说明有其他用法。

线程管理

QThread在started()和finished()时会发送一个信号,此外如果想检查的话,也可以通过isFinished()、isRunning()来检查线程的状态。

可以通过exit()、quit()来终止线程。有时,我们会想用terminate()来终止一个线程,但是这样做是危险且不推荐的。可以查看terminate()、setTerminationEnabled()来查看详细说明。

从Qt 4.8之后,可以在进程结束时,通过将finished()信号与QObject::deleteLater()连接,以释放资源。

调用wait()来阻塞一个线程,直到另一个线程finish,或者直到指定时间耗尽。

QThread也提供了一些static、平台无关的休眠函数:sleep()、msleep()、usleep(),这三个函数的功能类似,只是单位不同,分别是秒、毫秒、微秒。

注意

wait()和sleep()通常是不必要的,因为Qt是事件驱动的框架。不推荐调用wait(),可以用监听finished()信号并将它与另一个槽函数连接来代替;不推荐调用sleep(),推荐使用QTimer。

static方法currentThreadId()与currentThread()返回当前执行的线程,前一个函数返回线程ID,后一个返回线程指针。

为了选择线程名(Linux中通过ps -L命令来指定),我们可以在启动线程前调用setObjectName()。不调用该方法的话,线程名将是运行该线程的线程子类名。不过该名字在Windows系统中用release方式来编译代码时是不可用的。

1、模块和加载项

Header: #include <QThread>
qmake: QT += core
Inherits: QObject

2、构造与析构

QThread(QObject *parent = nullptr)

构造一个QThread来管理一个新线程。

parent是QThread的所有者。

该线程直至调用start()才会启动

~QThread()

破坏QThread。

注意:删除QThread将会stop线程的执行。删除一个运行中QThread将会导致程序碰撞。删除QThread前应该先等待finished()信号。

3、静态字段

enum Priority

{ IdlePriority, LowestPriority, LowPriority,

NormalPriority, HighPriority, …, InheritPriority }

线程优先级

Constant Value Description
QThread::IdlePriority 0 scheduled only when no other threads are running.
QThread::LowestPriority 1 scheduled less often than LowPriority.
QThread::LowPriority 2 scheduled less often than NormalPriority.
QThread::NormalPriority 3 the default priority of the operating system.
QThread::HighPriority 4 scheduled more often than NormalPriority.
QThread::HighestPriority 5 scheduled more often than HighPriority.
QThread::TimeCriticalPriority 6 scheduled as often as possible.
QThread::InheritPriority 7 use the same priority as the creating thread. This is the default.

4、静态方法

返回值类型

方法

说明

QThread *

create(Function &&f, Args &&... args)

create(Function &&f)

构造一个新的QThread,该线程将执行函数f,后边的参数是函数f的参数。

该线程并没有启动——必须直接通过start()才能启动。这允许我们连接它们的信号、把某些QObject转移到Thread中、确定优先级等。

支持参数的create方法只有在使用C++17时才能用。

不要多次在QThread中调用start()

QThread * currentThread() 返回当前执行的线程
Qt::HANDLE currentThreadId() 返回当前执行的线程的Handle
int idealThreadCount() 返回系统中能运行的线程的最大数量。
void sleep(unsigned long secs) 休眠若干秒
void msleep(unsigned long msecs) 休眠若干毫秒
void usleep(unsigned long usecs) 休眠若干微秒
void yieldCurrentThread()  

5、实例方法

返回值类型

方法

说明

QAbstractEventDispatcher * eventDispatcher() 指向该线程的Event Dispatcher。如果不存在时则返回nullptr。
protected int exec()

进入事件循环,直至调用exit(),返回传递给exit()的值。如果通过quit()调用exit()则返回0。

该方法内部将会执行run(),调用该方法来启动一个消息循环。

该方法只能被当前线程调用。

void exit(int returnCode = 0)

使线程的事件循环终止并返回一个returnCode。

0代表成功,非0代表失败。

bool

isFinished()

isInterruptionRequested()

isRunning()

如果线程完成时,返回true
如果在该线程中运行的任务需要被终止,返回true
当线程正在运行时,返回true
int loopLevel() 返回当前线程的事件循环等级。
QThread::Priority priority() 返回当前线程优先级。
void requestInterruption() 请求线程的中止。
void

setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)

setPriority(QThread::Priority priority)

setStackSize(uint stackSize)

设置EventDispatched、优先级、栈大小。
uint stackSize() 返回当前线程的栈大小
bool

wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))

wait(unsigned long time)

1、阻塞当前线程直到以下情况发生:

①该QThread相关的Thread完成执行;此时返回true

②deadline时间到了;此时返回false

2、等待若干秒

     

6、槽

quit()

使线程的事件循环退出,返回0(成功时)。等同于调用QThread::exit(0)。

如果不存在消息循环,该方法将什么都不做。

start(QThread::Priority priority = InheritPriority) 通过调用run()来运行该线程。OS将根据参数priority来调度线程。如果线程已经在运行了,那么该方法讲什么都不做。
terminate() 终止线程运行,不推荐。

7、信号

finished()

线程正要完成执行前发送该信号。

发送该信号之后,事件循环就停止了,不会有更多事件在线程中运行了,除非一些推迟的资源回收、删除事件。

该事件常与QObject::deleteLater()连接,用于释放线程中的资源。

注意:如果通过terminate()来终止进程,那么就不能确定该信号是被哪个线程发送了。

started() 当线程开始执行时发送该信号,在run()方法调用前。

最新文章

  1. 威佐夫博弈(Wythoff Game)
  2. nanoTime对volatile 测试的一种写法
  3. android开发中获取&lt;meta-data&gt;数据
  4. H2的MVStore
  5. Bean的生命周期
  6. MSP430F149学习之路——LED
  7. Web服务器与Servlet容器
  8. 1065. A+B and C (64bit)
  9. iOS Crash文件的解析
  10. hash表的创建
  11. Html5 Canvas Hit Testing
  12. SUSE 11下安装DPDK
  13. DoesNotExist at /admin/
  14. GA:利用GA对一元函数进行优化过程,求x∈(0,10)中y的最大值——Jason niu
  15. Linux 连接mysql
  16. 最棒的 JavaScript 学习指南(2018版)
  17. [JavaScript] 给input标签传值
  18. 转载:C++类内存分布
  19. React Native常用组件之ScrollView
  20. Uni2D入门

热门文章

  1. linux下查看 SELinux状态及关闭SELinux
  2. docker内存限制
  3. Android性能优化之Android 10+ dex2oat实践
  4. 解决github.com无法访问
  5. js获取高度
  6. java的本地文件操作
  7. CSS多种方式实现元素水平垂直居中
  8. Java架构师必备技能:docker使用大全
  9. verification 时间不推进,挂起
  10. JUC并发工具类之 CountDownLatch等待多线程完成