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()在终止被禁用的情况下被调用),该函数将立即终止调用线程。注意,这个函数在这种情况下不会返回。