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 对象管理程序中的一个控制线程。QThread 对象在调用 `run()` 时开始执行。默认情况下,`run()` 通过调用 `exec()` 来启动事件循环,并在该线程内运行一个 Qt 事件循环。
您可以通过调用QObject::moveToThread() 将工作者对象移入该线程来使用它们。
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();
}在此示例中,run 函数返回后,该线程将退出。除非调用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() 分别支持秒、毫秒和微秒级精度。
注意: 由于 Qt 是一个事件驱动的框架,因此通常无需使用wait() 和sleep() 函数。建议不要使用wait(),而应考虑监听finished() 信号;对于sleep() 函数,建议改用QChronoTimer 。
静态函数currentThreadId() 和currentThread() 返回当前正在执行的线程的标识符。前者返回线程的特定于平台的 ID;后者返回一个 QThread 指针。
若要指定线程的名称(例如,在 Linux 上通过ps -L 命令识别的名称),可以在启动线程之前调用setObjectName()。 若不调用setObjectName(),线程将自动采用其运行时类型的类名作为名称(例如,在曼德尔布罗特示例中为"RenderThread" ,因为这是QThread子类的名称)。请注意,此功能目前在Windows的正式发布版本中不可用。
另请参阅 Qt 中的多线程、QThreadStorage 、线程同步、曼德尔布罗集、使用信号量实现生产者-消费者模式,以及使用等待条件实现生产者-消费者模式。
成员类型文档
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 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() 来启动它。这允许您订阅其信号、将 QObject 移至该线程、设置新线程的优先级等。函数f 将在新线程中被调用。
返回新创建的 `QThread ` 实例。
注意:调用者 将获得返回的QThread 实例的所有权。
另请参阅 start()。
[static] QThread *QThread::currentThread()
返回一个指向QThread 的指针,该对象管理当前正在执行的线程。
[static noexcept] Qt::HANDLE QThread::currentThreadId()
返回当前正在执行的线程的线程句柄。
警告: 此函数返回的句柄仅用于内部用途,不应在任何应用程序代码中使用。
注意:在 Windows系统上 ,此函数返回的是 Win32 函数 GetCurrentThreadId() 返回的 DWORD(Windows 线程 ID),而不是 Win32 函数 GetCurrentThread() 返回的伪句柄(Windows 线程句柄)。
[override virtual] bool QThread::event(QEvent *event)
重写了:QObject::event(QEvent *e)。
QAbstractEventDispatcher *QThread::eventDispatcher() const
返回该线程的事件分发器对象的指针。如果该线程不存在事件分发器,则此函数返回nullptr 。
另请参阅 setEventDispatcher()。
[protected] int QThread::exec()
进入事件循环,并等待调用exit(),同时返回传递给exit()的值。如果通过quit()调用了exit(),则返回值为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() 函数的线程,但并非必然如此。它是处理GUI事件的线程,并且可以在该线程中创建图形对象(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
返回线程当前的服务质量(QoS)级别。
该函数在 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 参数的效果取决于操作系统的调度策略。特别地,在不支持线程优先级的系统上(例如Linux,更多详情请参阅http://linux.die.net/man/2/sched_setscheduler),该priority 将被忽略。
另请参阅 Priority 、priority() 以及start()。
[since 6.9] void QThread::setServiceLevel(QThread::QualityOfService serviceLevel)
将线程对象的服务质量级别设置为serviceLevel 。此函数只能在该线程内部或线程启动之前调用!
目前该功能仅在 Apple 平台和 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()` 设置);否则返回零。
另请参阅 setStackSize()。
[slot] void QThread::start(QThread::Priority priority = InheritPriority)
通过调用run() 开始执行该线程。操作系统将根据priority 参数对该线程进行调度。如果该线程已经在运行,则此函数不执行任何操作。
priority 参数的效果取决于操作系统的调度策略。特别地,在不支持线程优先级的系统上(例如 Linux,更多细节请参阅sched_setscheduler文档),priority 将被忽略。
[private signal] void QThread::started()
该信号由关联的线程在开始执行时发出,因此任何与其关联的槽都可能通过队列调用被调用。尽管该事件可能在调用run()之前已被发布,但任何跨线程的信号传递仍可能处于待处理状态。
注意:这是一个 私有信号。它可在信号连接中使用,但用户无法主动发出该信号。
[slot] void QThread::terminate()
终止线程的执行。该线程是否会立即终止取决于操作系统的调度策略。为确保安全,请在调用QThread::wait()后,再调用terminate()。
当线程终止时,所有正在等待该线程结束的线程都将被唤醒。
警告:此 函数存在风险,不建议使用。线程可能在其代码路径的任何位置被终止。线程在修改数据时也可能被终止。此时,线程将无法进行善后处理,也无法解锁持有的互斥锁等。简而言之,仅在绝对必要时才应使用此函数。
可以通过调用 `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。
设置为QDeadlineTimer::Forever (默认值)的截止时间计时器永远不会超时:在这种情况下,该函数仅在线程从run() 返回时,或者线程尚未启动时返回。
这提供了与 POSIXpthread_join() 函数类似的功能。
注意:在 某些操作系统上, 当操作系统线程仍在运行且可能正在执行清理代码(例如 C++11thread_local 析构函数)时,该函数可能会返回 true。在 Linux、Windows 和 Apple 操作系统等系统上,该函数仅在操作系统线程完全退出后才会返回 true。
bool QThread::wait(unsigned long time)
time 表示以毫秒为单位的等待时间。如果time 的值为ULONG_MAX,则等待将永远不会超时。
这是一个重载函数。
[static] void QThread::yieldCurrentThread()
将当前线程的执行权让给另一个可运行线程(如果存在的话)。请注意,由操作系统决定切换到哪个线程。
© 2026 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.