百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

QT(11)- QThread qt 使用c++ thread

liebian365 2024-10-17 14:00 6 浏览 0 评论

1 简介

QThread:具有可选事件循环的低级 API
QThread是 Qt 中所有线程控制的基础。每个QThread实例表示并控制一个线程。

QThread可以直接实例化,也可以子类化。实例化QThread提供了一个并行事件循环,允许在辅助线程中调用QObject插槽。对 QThread进行子类化允许应用程序在启动其事件循环之前初始化新线程,或者在没有事件循环的情况下运行并行代码。

QThread 会在线程运行时通过信号通知你started() 和finished(), 或者你可以使用isFinished() 和isRunning() 来查询线程的状态。

您可以通过调用停止线程exit() 或者quit(). 在极端情况下,您可能想要强行terminate() 一个正在执行的线程。然而,这样做是危险的。

使用wait() 阻塞调用线程,直到另一个线程完成执行(或直到指定的时间过去)。

QThread 还提供静态的、平台独立的休眠函数:sleep(),msleep(), 和usleep() 分别允许完整的秒、毫秒和微秒分辨率。

2 枚举

3 函数

3.1 eventDispatch

QAbstractEventDispatcher *QThread::eventDispatcher() const
它返回线程内部的事件分发器。
事件分发器是Qt内部使用的对象,用于分发事件到与线程关联的对象。它是Qt事件系统的一部分,在应用程序的主线程中,事件分发器会在事件循环中不断地分发事件。在其他线程中,事件分发器用于处理线程相关的事件,例如,线程完成信号或其他自定义事件。

通过使用这个函数,可以访问该线程内部的事件分发器,并对其进行配置或访问。但是,一般情况下,不需要直接访问事件分发器。

void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
setEventDispatcher 是QThread类中的一个成员函数,用于在线程中设置一个事件分发器。

这个函数接受一个QAbstractEventDispatcher指针作为参数,并将其设置为线程的事件分发器。事件分发器是Qt内部使用的对象,用于处理线程内部的事件。通过使用这个函数,可以为线程定制事件分发器,以满足特定需求。

一般情况下,不需要使用这个函数,因为Qt会自动为每个线程分配一个适当的事件分发器。但是,如果需要定制线程内部的事件处理,则可以使用这个函数。

3.2 exit

void QThread::exit(int returnCode = 0)
exit 函数告诉线程的事件循环(不是线程)退出,并以一个返回码作为结果。

调用此函数后,该线程离开事件循环并从调用 QEventLoop::exec() 的地方返回。 QEventLoop::exec() 函数的返回值为 returnCode。

按照惯例,returnCode 为0表示成功,任何非零值表示错误。

请注意,与同名的C库函数不同,该函数确实返回给调用者,因为是事件处理停止了。

在此线程中,不会再启动任何QEventLoop,直到再次调用 QThread::exec()。如果 QThread::exec() 中的事件循环没有运行,则下一次调用 QThread::exec() 也将立即返回。

使用该函数的常见场景是在线程中执行任务完成后终止线程的执行,以避免在没有任务的情况下继续执行无用代码。

3.3 isfinished

bool QThread::isFinished() const
该函数用于检查线程是否已经结束。如果线程已结束,则返回 true,否则返回 false。

线程的结束是指该线程的 run() 函数已经返回。因此,在线程结束后,如果再次调用该函数,它将返回 true。

3.4 requestInterruption

bool isInterruptionRequested() const
如果应该停止在此线程上运行的任务,则返回 true。可以通过以下方式请求中断requestInterruption().

此功能可用于使长时间运行的任务完全可中断。永远不要检查或操作此函数返回的值是安全的,但建议在长时间运行的函数中定期这样做。注意不要过于频繁地调用它,以保持较低的开销。

该函数返回一个布尔值,表示线程是否被请求中断。

应用场景:当我们需要在线程运行时随时取消它,可以使用该函数来实现。

方法:

首先需要在线程的实现中,定期调用该函数,如果函数返回 true,表示线程被请求中断。
然后退出线程的循环,让线程终止。

void MyThread::run()
{
while (!isInterruptionRequested())
{
//do some work
//check periodically if the thread needs to be stopped
}
}
QThread *thread = new QThread;
thread->start();
//Later, in another thread
thread->requestInterruption();

void requestInterruption()
请求中断线程。该请求是建议性的,由线程上运行的代码决定是否以及如何响应此类请求。此函数不会停止线程上运行的任何事件循环,也不会以任何方式终止它。

3.5 isRunning

bool QThread::isRunning() const
true如果线程正在运行则返回;否则返回false。

3.4 loopLevel

int QThread::loopLevel() const
QThread::loopLevel() 函数是 Qt 库中的成员函数,用于返回当前线程的事件循环深度。事件循环深度指的是在当前线程中有多少个事件循环正在执行。

例如,如果当前线程中有一个事件循环正在执行,那么 QThread::loopLevel() 函数将返回 1;如果当前线程中有两个事件循环正在执行,那么函数将返回 2,以此类推。

可以通过这个函数来判断线程中是否存在事件循环,从而决定是否执行一些特定的操作。

3.5 priority

QThread::Priority QThread::priority() const
返回正在运行的线程的优先级。如果线程未运行,则此函数返回InheritPriority

void setPriority(QThread::Priority priority)
这个函数用于设置正在运行的线程的优先级。如果线程没有运行,则此函数什么也不做,并立即返回。要以特定优先级启动线程,请使用start()。

priority参数可以是QThread :: Priority枚举中的任何值,除了InheritPriority。

优先级参数的效果取决于操作系统的调度策略。特别是,在不支持线程优先级的系统上(例如Linux)

3.6 StackSize 堆栈大小

void QThread::setStackSize(uint stackSize)
这个函数用于设置线程的堆栈大小。如果线程正在运行,则此函数不会有任何效果,并立即返回。如果要以特定的堆栈大小启动线程,请使用start()。

stackSize参数是堆栈大小,以字节为单位。默认堆栈大小取决于操作系统,通常为2 MB。

注意:在某些操作系统上,设置堆栈大小不受支持,在这些系统上,该函数可能不起作用,因此需要检查该函数的返回值。

uint QThread::stackSize() const
返回线程的最大堆栈大小(如果设置为setStackSize()); 否则返回零。

3.7 wait

bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
这个函数会等待线程结束,直到 deadline 到期。
bool wait(unsigned long time)
这个函数会等待线程结束,最多等待 time 毫秒。

如果在等待期间线程已经结束,那么两个函数都会立即返回 true。否则,如果等待超时或者等待被其他线程中断,那么它们将返回 false。

如果等待的时间到了,但是线程还没有结束,那么 wait() 函数将返回 false。这表示在等待的过程中,线程没有终止,因此不需要等待

4 虚函数

virtual bool event(QEvent *event) override

event() 是 QObject 类中的虚拟函数,在继承类中被重写可以自定义处理事件。QThread 继承自 QObject,所以也可以重写 event() 函数。

event() 函数通过接收到的 QEvent 对象参数来处理不同类型的事件。这样,你可以定制线程的行为,比如,当线程接收到一个特定的事件时,它可以做出特定的反应。

在 event() 函数中,你可以对事件进行判断,根据事件类型执行不同的操作。如果 event() 函数返回 true,那么这个事件就被认为已经处理过;否则,事件会继续传递到父对象。

注意:QThread 不是一个 GUI 线程,所以不能在它的 event() 函数中调用 GUI 函数(例如:QMessageBox)。如果需要在线程中调用 GUI 函数,请使用 signals 和 slots。

5 Public Slots

5.1 quit

void quit()
告诉线程的事件循环以返回码 0(成功)退出。相当于调用QThread::exit(0).
如果线程没有事件循环,则此函数不执行任何操作。

5.2 start

void start(QThread::Priority priority = InheritPriority)
通过调用开始执行线程run(). 操作系统会根据priority范围。如果线程已经在运行,则此函数不执行任何操作。
的影响priority参数取决于操作系统的调度策略。特别是,priority在不支持线程优先级的系统上将被忽略(例如在 Linux 上)

因为优先级需要在线程运行的时候设置,所以如果需要设置优先级,可以在使用start时就直接设置。

5.3 terminate

void terminate()
这个函数是用来终止线程的执行的。根据操作系统的调度策略,线程可能立刻终止,也可能不会。在使用terminate()函数后,使用QThread::wait()来确保线程已经终止。

当线程终止时,所有等待该线程结束的线程将被唤醒。

注意,使用 "terminate()" 终止线程是不推荐的,因为它可能导致线程执行未完成的任务,导致程序状态不一致。正确的做法是在线程执行代码中设置标志,让线程自行退出

6 信号

void finished()
finished() 是 QThread 类的信号,在线程结束后发出。这个信号通常用来在线程结束后释放相关资源,或执行清理操作。

换句话说,它是一个通知,告诉线程的使用者,线程已经结束了。

这个信号可以连接到QObject::deleteLater(), 以释放该线程中的对象。

注意:如果关联的线程被终止使用terminate(), 未定义从哪个线程发出该信号。

注意:这是一个私人信号。它可用于信号连接,但不能由用户发射。

void started()
当相关线程开始执行时,在调用run()函数之前,该信号从线程发出。

注意:这是一个私有信号。它可用于信号连接,但不能由用户发出。

7 静态公有函数

7.1 create

QThread * create(Function &&f, Args &&... args)
c++17标准适用

template <typename Function> QThread *QThread::create(Function &&f)
创建一个新的QThread对象,它将执行函数f。

新线程没有启动——它必须通过显式调用start()来启动。这允许您连接到它的信号,将QObjects移动到线程,选择新线程的优先级等等。函数f将在新线程中被调用。

返回新创建的QThread实例。

注意:调用者获得返回的QThread实例的所有权。

警告:不要在返回的QThread实例上调用start()超过一次;这样做将导致未定义的行为。

7.2 currentThread

QThread * currentThread()
返回一个指向QThread的指针,该QThread管理当前执行的线程

7.3 currentThreadId

Qt::HANDLE currentThreadId()
返回当前执行线程的线程句柄。

警告:此函数返回的句柄用于内部目的,不应在任何应用程序代码中使用。

注意:在Windows上,这个函数返回由Win32函数GetCurrentThreadId()返回的DWORD (Windows- thread ID),而不是由Win32函数GetCurrentThread()返回的伪句柄(Windows- thread句柄)。

7.4 idealThreadCount

int idealThreadCount()
返回系统上可以运行的理想线程数。这是通过查询系统中实际的和逻辑的处理器内核数量来完成的。如果无法检测到处理器核数,则此函数返回1。

7.5 sleep

void msleep(unsigned long msecs)
强制当前线程休眠msecs毫秒。

如果需要等待给定条件的改变,请避免使用此函数。相反,将插槽连接到指示更改的信号或使用事件处理程序(参见QObject::event())。

注意:此函数不保证准确性。在重载条件下,应用程序的睡眠时间可能超过msec。一些操作系统可能把毫秒四舍五入到10毫秒或15毫秒。

void sleep(unsigned long secs)

void usleep(unsigned long usecs)
微秒

7.6 yieldCurrentThread

void yieldCurrentThread()
将当前线程的执行传递给另一个可运行的线程(如果有的话)。注意,由操作系统决定切换到哪个线程。

8 Protected Functions

8.1 exec

int exec()
进入事件循环并等待,直到调用exit(),返回传递给exit()的值。如果通过quit()调用exit(),则返回值为0。

该函数将在run()中调用。必须调用此函数来启动事件处理。

注意:这只能在线程本身中调用,即当它是当前线程时。

8.2 run

virtual void run()
线程的起始点。在调用start()之后,新创建的线程调用这个函数。默认实现只调用exec()。

您可以重新实现此函数以方便高级线程管理。从这个方法返回将结束线程的执行。

9 Static Protected Members

void setTerminationEnabled(bool enabled = true)
基于enabled参数启用或禁用当前线程的终止。线程必须是由QThread启动的。

当enabled为false时,终止被禁用。以后对QThread::terminate()的调用将立即返回而不生效。相反,终止将被推迟,直到启用终止。

当enabled为true时,终止被启用。以后对QThread::terminate()的调用将正常终止线程。如果终止被延迟(即QThread::terminate()在终止被禁用的情况下被调用),该函数将立即终止调用线程。注意,这个函数在这种情况下不会返回。

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: