QThread Class
QThread 类提供了一种独立于平台的线程管理方式。更多
头文件: | #include <QThread> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
qmake: | QT += core |
继承: | QObject |
- 所有成员(包括继承成员)的列表
- QThread 属于线程类。
公共类型
enum | Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, …, InheritPriority } |
(since 6.9) enum class | QualityOfService { Auto, High, Eco } |
公共函数
QThread(QObject *parent = nullptr) | |
virtual | ~QThread() |
QAbstractEventDispatcher * | eventDispatcher() const |
(since 6.8) bool | isCurrentThread() const |
bool | isFinished() const |
bool | isInterruptionRequested() const |
bool | isRunning() const |
int | loopLevel() const |
QThread::Priority | priority() const |
void | requestInterruption() |
(since 6.9) QThread::QualityOfService | serviceLevel() const |
void | setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) |
void | setPriority(QThread::Priority priority) |
(since 6.9) void | setServiceLevel(QThread::QualityOfService serviceLevel) |
void | setStackSize(uint stackSize) |
uint | stackSize() const |
bool | wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) |
bool | wait(unsigned long time) |
重新实现的公共函数
virtual bool | event(QEvent *event) override |
公共插槽
void | exit(int returnCode = 0) |
void | quit() |
void | start(QThread::Priority priority = InheritPriority) |
void | terminate() |
信号
静态公共成员
QThread * | create(Function &&f, Args &&... args) |
QThread * | currentThread() |
Qt::HANDLE | currentThreadId() |
int | idealThreadCount() |
(since 6.8) bool | isMainThread() |
void | msleep(unsigned long msecs) |
(since 6.6) void | sleep(std::chrono::nanoseconds nsecs) |
void | sleep(unsigned long secs) |
void | usleep(unsigned long usecs) |
void | yieldCurrentThread() |
受保护函数
静态受保护成员
void | setTerminationEnabled(bool enabled = true) |
详细说明
QThread 对象管理程序中的一个控制线程。QThreads 在run() 中开始执行。默认情况下,run() 通过调用exec() 启动事件循环,并在线程内运行 Qt 事件循环。
您可以使用QObject::moveToThread() 将 Worker 对象移动到线程中。
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 插槽中的代码将在单独的线程中执行。不过,您可以自由地将 Worker 插槽连接到任何线程中任何对象的任何信号。在不同线程间连接信号和槽是安全的,这要归功于一种名为queued connections 的机制。
另一种让代码在独立线程中运行的方法是子类化 QThread 并重新实现run() 。例如
class WorkerThread : public QThread { Q_OBJECT public: explicit WorkerThread(QObject *parent = nullptr) : QThread(parent) { } protected: void run() override { QString result; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: void resultReady(const QString &s); }; void MyObject::startWorkInAThread() { WorkerThread *workerThread = new WorkerThread(this); connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults); connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater); workerThread->start(); }
在该示例中,线程将在运行函数返回后退出。除非调用exec() ,否则不会有任何事件循环在线程中运行。
请务必记住,QThread 实例lives in 是实例化它的旧线程,而不是调用run() 的新线程。这意味着 QThread 的所有队列槽和invoked methods 都将在旧线程中执行。因此,希望在新线程中调用插槽的开发人员必须使用工作对象方法;新插槽不应直接在子类 QThread 中实现。
与队列插槽或调用方法不同,直接在 QThread 对象上调用的方法将在调用该方法的线程中执行。在子类化 QThread 时,请记住构造函数在旧线程中执行,而run() 则在新线程中执行。如果一个成员变量在两个函数中都被访问,那么该变量就会在两个不同的线程中被访问。请检查这样做是否安全。
注意: 在不同线程间与对象交互时必须小心谨慎。一般来说,除非文档另有说明,否则只能从创建 QThread 对象的线程调用函数(如setPriority() )。详情请参阅同步线程。
管理线程
当线程处于started() 和finished() 时,QThread 会通过信号通知你,你也可以使用isFinished() 和isRunning() 来查询线程的状态。
您可以调用exit() 或quit() 停止线程。在极端情况下,您可能想强行terminate() 正在执行的线程。但是,这样做是危险的,也是不可取的。有关详细信息,请阅读terminate() 和setTerminationEnabled() 文档。
当一个线程结束时,你通常会想去分配线程中的对象。为此,请将finished() 信号连接到QObject::deleteLater() 。
使用wait() 阻止调用线程,直到其他线程执行完毕(或指定时间已过)。
QThread 还提供了独立于平台的静态睡眠函数:sleep(),msleep(), 和usleep() 分别支持全秒、毫秒和微秒分辨率。
注意: wait() 和sleep() 函数在一般情况下应该是不必要的,因为 Qt XML 是一个事件驱动框架。与其使用wait() 函数,不如考虑监听finished() 信号。考虑使用QChronoTimer 代替sleep() 函数。
静态函数currentThreadId() 和currentThread() 返回当前执行线程的标识符。前者返回线程的平台特定 ID,后者返回 QThread 指针。
要选择线程的名称(例如,Linux 上的ps -L
命令所标识的名称),可以在启动线程前调用setObjectName() 。如果不调用setObjectName() ,线程的名称将是线程对象运行时类型的类名(例如,在Mandelbrot示例中为"RenderThread"
,因为这是 QThread 子类的名称)。请注意,目前 Windows 上的发布版本还不提供此功能。
另请参阅 Qt 中的线程支持、QThreadStorage 、同步线程、Mandelbrot、使用 Semaphores 的生产者和消费者以及使用等待条件的生产者和消费者。
成员类型文档
enum QThread::Priority
该枚举类型表示操作系统应如何调度新创建的线程。
常量 | 值 | 说明 |
---|---|---|
QThread::IdlePriority | 0 | 仅在没有其他线程运行时调度。 |
QThread::LowestPriority | 1 | 调度频率低于 LowPriority。 |
QThread::LowPriority | 2 | 比 NormalPriority(正常优先级)更少调度。 |
QThread::NormalPriority | 3 | 操作系统的默认优先级。 |
QThread::HighPriority | 4 | 比 NormalPriority(正常优先级)更频繁地调度。 |
QThread::HighestPriority | 5 | 比 HighPriority(高优先级)更频繁地调度。 |
QThread::TimeCriticalPriority | 6 | 尽可能频繁地调度。 |
QThread::InheritPriority | 7 | 使用与创建线程相同的优先级。这是默认值。 |
[since 6.9]
enum class QThread::QualityOfService
该枚举描述了线程的服务质量级别,并为调度程序提供了有关线程所执行工作类型的信息。在具有不同 CPU 配置文件的平台上,或在能降低 CPU 某些内核时钟频率的平台上,调度程序可利用此枚举为线程选择或配置具有合适性能和能耗特性的 CPU 内核。
常数 | 值 | 说明 |
---|---|---|
QThread::QualityOfService::Auto | 0 | 默认值,由调度程序决定在哪个 CPU 内核上运行线程。 |
QThread::QualityOfService::High | 1 | 调度程序应在高性能 CPU 内核上运行该线程。 |
QThread::QualityOfService::Eco | 2 | 调度程序应在节能的 CPU 内核上运行该线程。 |
此枚举在 Qt 6.9 中引入。
另请参阅 Priority,serviceLevel() 和QThreadPool::serviceLevel() 。
成员函数文档
[explicit]
QThread::QThread(QObject *parent = nullptr)
构造一个新的 QThread 来管理一个新线程。parent 拥有 QThread 的所有权。在调用start() 之前,线程不会开始执行。
另请参阅 start() 。
[virtual noexcept]
QThread::~QThread()
销毁QThread 。
请注意,删除QThread 对象不会停止其管理的线程的执行。删除正在运行的QThread (即isFinished() 返回false
)将导致程序崩溃。删除QThread 之前,请等待finished() 信号。
自 Qt XML 6.3 起,允许删除通过调用QThread::create() 创建的QThread 实例,即使相应的线程仍在运行。在这种情况下,Qt 将向该线程发出中断请求(通过requestInterruption() );要求该线程的事件循环(如果有的话)退出(通过quit() );并阻塞直到该线程结束。
另请参阅 create()、isInterruptionRequested()、exec() 和quit()。
[static]
template <typename Function, typename... Args> QThread *QThread::create(Function &&f, Args &&... args)
创建一个新的QThread 对象,执行带有参数args 的函数f 。
新线程不会启动,必须通过明确调用start() 才能启动。这样,您就可以连接到它的信号、将 QObjects 移动到线程、选择新线程的优先级等。函数f 将在新线程中调用。
返回新创建的QThread 实例。
注意: 调用者将获得返回的QThread 实例的所有权。
另请参阅 start()。
[static]
QThread *QThread::currentThread()
返回指向QThread 的指针,该指针用于管理当前执行的线程。
[static noexcept]
Qt::HANDLE QThread::currentThreadId()
返回当前执行线程的线程句柄。
警告 此函数返回的句柄用于内部目的,不应在任何应用代码中使用。
注意: 在 Windows 系统中,此函数返回的是由 Win32 函数 GetCurrentThreadId() 返回的 DWORD(Windows-线程 ID),而不是由 Win32 函数 GetCurrentThread() 返回的伪 HANDLE(Windows-线程句柄)。
[override virtual]
bool QThread::event(QEvent *event)
重实现:QObject::event(QEvent *e)。
QAbstractEventDispatcher *QThread::eventDispatcher() const
返回指向线程的事件派发器对象的指针。如果线程不存在事件派发器,该函数将返回nullptr
。
另请参见 setEventDispatcher()。
[protected]
int QThread::exec()
进入事件循环,等待exit() 被调用,并返回传递给exit() 的值。如果exit() 是通过quit() 调用的,则返回值为 0。
该函数应在run() 中调用。必须调用该函数才能开始事件处理。
注意: 该函数只能在线程内部调用,即在当前线程中调用。
[slot]
void QThread::exit(int returnCode = 0)
告诉线程的事件循环以返回代码退出。
调用该函数后,线程离开事件循环,并从调用QEventLoop::exec() 返回。QEventLoop::exec() 函数返回returnCode 。
按照惯例,returnCode 为 0 表示成功,任何非零值都表示出错。
请注意,与 C 库中的同名函数不同,该函数确实会返回给调用者,但停止的是事件处理。
在再次调用QThread::exec() 之前,该线程不会再启动 QEventLoop。如果QThread::exec() 中的事件循环没有运行,那么下一次调用QThread::exec() 也将立即返回。
注意:此函数是线程安全的。
另请参见 quit() 和QEventLoop 。
[private signal]
void QThread::finished()
该信号由相关线程在执行结束前发出。
发出该信号时,事件循环已停止运行。除延迟删除事件外,该线程将不再处理其他事件。该信号可以连接到QObject::deleteLater() ,以释放该线程中的对象。
注: 如果相关线程已使用terminate() 终止,则未定义此信号是从哪个线程发出的。
注: 这是一个私有信号。它可以在信号连接中使用,但不能由用户发出。
另请参见 started()。
[static noexcept]
int QThread::idealThreadCount()
返回此进程可并行运行的理想线程数。具体方法是查询该进程可用的逻辑处理器数量(如果操作系统支持)或系统中逻辑处理器的总数。如果两个值都无法确定,该函数将返回 1。
注意: 在支持将线程的亲和性设置为所有逻辑处理器子集的操作系统上,此函数返回的值可能会随线程的不同和时间的推移而变化。
注意: 在支持 CPU 热插拔的操作系统上,此函数返回的值也可能随时间而变化(注意,CPU 可以通过软件打开或关闭,而无需物理、硬件变化)。
[noexcept, since 6.8]
bool QThread::isCurrentThread() const
如果此线程为QThread::currentThread ,则返回 true。
此函数在 Qt 6.8 中引入。
另请参阅 currentThreadId()。
bool QThread::isFinished() const
如果线程已结束,则返回true
;否则返回false
。
如果线程已从run() 函数返回,且已发出finished() 信号,则认为线程已结束。
请注意,在finished() 信号发出后,线程仍可运行任意时间,进行清理操作,如执行thread_local
变量的析构函数。要与线程的所有效果同步,请调用wait() 并验证是否返回 true。
注意:该函数是线程安全的。
另请参见 isRunning()。
bool QThread::isInterruptionRequested() const
如果应停止在此线程上运行的任务,则返回 true。可以通过requestInterruption() 请求中断。
该函数可用于使长时间运行的任务干净利落地中断。从不检查或执行该函数返回的值是安全的,但建议在长时间运行的函数中定期这样做。注意不要频繁调用,以降低开销。
void long_task() { forever { if ( QThread::currentThread()->isInterruptionRequested() ) { return; } } }
注意: 该函数只能在线程内部调用,即在当前线程中调用。
另请参阅 currentThread() 和requestInterruption()。
[static noexcept, since 6.8]
bool QThread::isMainThread()
返回当前执行线程是否为主线程。
主线程是创建QCoreApplication 的线程。它通常是调用main()
函数的线程,但也不一定。它是处理图形用户界面事件的线程,在该线程中可以创建图形对象 (QWindow,QWidget)。
该函数在 Qt 6.8 中引入。
另请参阅 currentThread() 和QCoreApplication::instance()。
bool QThread::isRunning() const
如果线程正在运行,则返回true
;否则返回false
。
如果QThread 已通过start() 启动,但尚未结束,则认为线程正在运行。
请注意,在finished() 信号发出后,线程仍可运行任意时间,进行清理操作,如执行thread_local
变量的析构函数。要与线程的所有效果同步,请调用wait() 并验证是否返回 true。
注意:该函数是线程安全的。
另请参见 isFinished()。
int QThread::loopLevel() const
返回线程的当前事件循环级别。
注意: 只能在线程本身(即当前线程)内调用。
[static]
void QThread::msleep(unsigned long msecs)
这是一个重载函数,相当于调用:
QThread::sleep(std::chrono::milliseconds{msecs});
注意: 此函数不保证准确性。在负载较重的情况下,应用程序的休眠时间可能长于msecs 。某些操作系统可能会将msecs 四舍五入到 10 毫秒或 15 毫秒。
QThread::Priority QThread::priority() const
返回运行中线程的优先级。如果线程未运行,则此函数返回InheritPriority
。
另请参见 Priority,setPriority() 和start()。
[slot]
void QThread::quit()
告诉线程的事件循环以返回代码 0(成功)退出。相当于调用QThread::exit(0)。
如果线程没有事件循环,则此函数不会执行任何操作。
注意:此函数对线程安全。
另请参阅 exit() 和QEventLoop 。
void QThread::requestInterruption()
请求中断线程。该请求是咨询性的,由线程上运行的代码决定是否以及如何执行该请求。该函数不会停止线程上运行的任何事件循环,也不会以任何方式终止线程。
注意:此函数是线程安全的。
另请参见 isInterruptionRequested()。
[virtual protected]
void QThread::run()
线程的起点。调用start() 后,新创建的线程会调用该函数。默认实现只是调用exec() 。
您可以重新实现该函数,以方便进行高级线程管理。从该方法返回将结束线程的执行。
[since 6.9]
QThread::QualityOfService QThread::serviceLevel() const
返回线程的当前服务质量级别。
此函数在 Qt 6.9 中引入。
另请参阅 setServiceLevel() 和QThreadPool::serviceLevel()。
void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
将线程的事件派发器设置为eventDispatcher 。只有在线程尚未安装事件派发器的情况下才会这样做。
在实例化QCoreApplication 时,会自动为主线程创建事件派发器,在start() 时,会自动为辅助线程创建事件派发器。
该方法获取对象的所有权。
另请参阅 eventDispatcher() 。
void QThread::setPriority(QThread::Priority priority)
此函数为运行中的线程设置priority 。如果线程未运行,则该函数不会执行任何操作并立即返回。使用start() 可以启动具有特定优先级的线程。
priority 参数可以是QThread::Priority
枚举中的任何值,但InheritPriority
除外。
priority 参数的作用取决于操作系统的调度策略。特别是,在不支持线程优先级的系统中,priority 将被忽略(如 Linux 系统,详情请参见 http://linux.die.net/man/2/sched_setscheduler)。
另请参阅 Priority 、priority() 和start()。
[since 6.9]
void QThread::setServiceLevel(QThread::QualityOfService serviceLevel)
将线程对象的服务质量级别设置为serviceLevel 。只能在线程本身或线程启动前调用!
目前仅在苹果平台和 Windows 平台上实现。该函数调用将在其他平台上成功完成,但目前不会产生任何影响。
此函数在 Qt 6.9 中引入。
另请参阅 serviceLevel() 和QThreadPool::setServiceLevel()。
void QThread::setStackSize(uint stackSize)
将线程的堆栈大小设置为stackSize 。如果stackSize 为零,操作系统或运行时将选择默认值。否则,线程的堆栈大小将是所提供的值(可四舍五入)。
在大多数操作系统中,为堆栈分配的内存大小最初会小于stackSize ,并随着线程使用堆栈而增加。该参数设置了允许堆栈增长的最大大小(即堆栈允许占用的虚拟内存空间大小)。
此函数只能在线程启动前调用。
警告 大多数操作系统都对线程堆栈大小设置了最小和最大限制。如果堆栈大小超出这些限制,线程将无法启动。
另请参见 stackSize().
[static protected]
void QThread::setTerminationEnabled(bool enabled = true)
根据enabled 参数启用或禁用终止当前线程。线程必须由QThread 启动。
当enabled 为 false 时,终止将被禁用。今后调用QThread::terminate() 将立即返回,不会产生任何影响。相反,终止将被推迟,直到启用终止。
enabled 为 true 时,启用终止。以后调用QThread::terminate() 将正常终止线程。如果终止已被推迟(即调用QThread::terminate() 时已禁用终止),该函数将立即终止调用线程。请注意,在这种情况下该函数不会返回。
另请参见 terminate()。
[static, since 6.6]
void QThread::sleep(std::chrono::nanoseconds nsecs)
强制当前线程休眠nsecs 。
如果需要等待给定条件发生变化,请避免使用此函数。取而代之的是,将槽连接到指示变化的信号,或使用事件处理程序(请参阅QObject::event() )。
注意: 此函数不保证准确性。在负载较重的情况下,应用程序的睡眠时间可能长于nsecs 。
此函数在 Qt 6.6 中引入。
[static]
void QThread::sleep(unsigned long secs)
强制当前线程休眠secs 秒。
这是一个重载函数,相当于调用:
QThread::sleep(std::chrono::seconds{secs});
uint QThread::stackSize() const
返回线程的最大堆栈大小(如果使用setStackSize() 设置),否则返回 0。
另请参见 setStackSize()。
[slot]
void QThread::start(QThread::Priority priority = InheritPriority)
通过调用run() 开始执行线程。操作系统将根据priority 参数调度线程。如果线程已在运行,则该函数不会执行任何操作。
priority 参数的作用取决于操作系统的调度策略。特别是在不支持线程优先级的系统中,priority 将被忽略(例如在 Linux 系统中,详情请参见sched_setscheduler文档)。
[private signal]
void QThread::started()
该信号在相关线程开始执行时发出,因此与之相连的任何槽都可能通过队列调用的方式被调用。虽然事件可能已在调用run() 之前发布,但信号的任何跨线程传递可能仍在等待中。
注意: 这是一个私有信号。它可以在信号连接中使用,但不能由用户发出。
[slot]
void QThread::terminate()
终止线程的执行。线程可能会也可能不会立即终止,这取决于操作系统的调度策略。为确保万无一失,请在 terminate() 之后使用QThread::wait() 。
线程终止后,所有等待线程结束的线程都会被唤醒。
警告: 此函数很危险,不建议使用。线程可以在其代码路径的任何位置被终止。线程可以在修改数据时被终止。线程没有机会自行清理、解锁任何持有的互斥等。简而言之,只有在绝对必要的情况下才能使用该功能。
可以通过调用QThread::setTerminationEnabled() 来显式启用或禁用终止。在终止被禁用时调用该函数会导致终止被推迟,直到终止被重新启用。更多信息,请参阅QThread::setTerminationEnabled() 文档。
注意:此函数是线程安全的。
另请参见 setTerminationEnabled()。
[static]
void QThread::usleep(unsigned long usecs)
这是一个重载函数,相当于调用:
QThread::sleep(std::chrono::microseconds{secs});
注意: 此函数不保证准确性。在负载较重的情况下,应用程序的睡眠时间可能长于usecs 。某些操作系统可能会将usecs 四舍五入到 10 毫秒或 15 毫秒;在 Windows 系统中,它将四舍五入到 1 毫秒的倍数。
bool QThread::wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
阻塞线程,直到满足上述任一条件:
- 与此QThread 对象关联的线程已执行完毕(即从run() 返回时)。如果线程已执行完毕,该函数将返回 true。如果线程尚未启动,也会返回 true。
- deadline 。如果到达截止时间,该函数将返回 false。
将 deadline 定时器设置为QDeadlineTimer::Forever
(默认值)将永远不会超时:在这种情况下,只有当线程从run() 返回或线程尚未启动时,函数才会返回。
这提供了与 POSIXpthread_join()
函数类似的功能。
注意: 在某些操作系统上,当操作系统线程仍在运行并执行清理代码(如 C++11thread_local
析构函数)时,该函数可能会返回 true。只有在操作系统线程完全退出后,该函数才会返回 true,这些操作系统包括 Linux、Windows 和 Apple 操作系统。
bool QThread::wait(unsigned long time)
这是一个重载函数。
time 是等待时间(毫秒)。如果 为 ULONG_MAX,则等待永不超时。time
[static]
void QThread::yieldCurrentThread()
将当前线程交给另一个可运行线程(如果有)执行。请注意,切换到哪个线程由操作系统决定。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.