QThread 类

QThread 类提供独立于平台的线程管理办法。 更多...

Header: #include <QThread>
CMake: find_package(Qt6 COMPONENTS Core REQUIRED)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core
继承: QObject

公共类型

enum Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority, …, InheritPriority }

公共函数

QThread (QObject * parent = nullptr)
virtual ~QThread ()
QAbstractEventDispatcher * eventDispatcher () const
void exit (int returnCode = 0)
bool isFinished () const
bool isInterruptionRequested () const
bool isRunning () const
int loopLevel () const
QThread::Priority priority () const
void requestInterruption ()
void setEventDispatcher (QAbstractEventDispatcher * eventDispatcher )
void setPriority (QThread::Priority priority )
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 quit ()
void start (QThread::Priority priority = InheritPriority)
void terminate ()

信号

void finished ()
void started ()

静态公共成员

QThread * create (Function && f , Args &&... args )
QThread * currentThread ()
Qt::HANDLE currentThreadId ()
int idealThreadCount ()
void msleep (unsigned long msecs )
void sleep (unsigned long secs )
void usleep (unsigned long usecs )
void yieldCurrentThread ()

保护函数

int exec ()
virtual void run ()

静态保护成员

void setTerminationEnabled (bool enabled = true)

详细描述

QThread 对象管理程序中的某一控制线程。QThread 开始执行在 run ()。默认情况下, run () 启动事件循环通过调用 exec () 并在线程内运行 Qt 事件循环。

可以使用 Worker 对象,通过把它们移动到线程使用 QObject::moveToThread ().

class Worker : public QObject
{
    Q_OBJECT
public slots:
    void doWork(const QString &parameter) {
        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 槽连接到来自任何对象、任何线程中的任何信号是自由的。跨不同线程连接信号和槽是安全的,得益于机制 队列连接 .

使代码运行在单独线程的另一办法,是子类 QThread 并重实现 run ()。例如:

class WorkerThread : public QThread
{
    Q_OBJECT
    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 实例 活在 实例化它的旧线程,而不是新线程调用 run ()。这意味着所有 QThread 的队列槽和 援引方法 都将在旧线程中执行。因此,希望在新线程中援引槽的开发者,必须使用 worker-object 方式;新的槽不应被直接实现到 QThread 子类中。

不像队列槽 (或援引方法),直接在 QThread 对象中被调用的方法,将在调用方法的线程中执行。当子类化 QThread 时,请记住构造函数在旧线程中执行,而 run () 在新线程中执行。若从两者函数访问成员变量,则变量是从 2 不同线程被访问。检查这样做是安全的。

注意: 当与跨不同线程的对象交互时必须小心。作为一般规则,只能从创建 QThread 对象本身的线程调用函数 (如 setPriority ()),除非文档编制另有说明。见 同步线程 了解细节。

管理线程

QThread 将凭借信号通知您当线程 started () 和 finished (),或可以使用 isFinished () 和 isRunning () 去查询线程的状态。

可以停止线程通过调用 exit () 或 quit ()。在极端情况下,可能希望强制 terminate () 执行线程。然而,这样做是危险的且不鼓励。请阅读文档编制为 terminate () 和 setTerminationEnabled () 为详细信息。

从 Qt 4.8 起,解除活在刚结束线程中的对象的分配是可能的,通过连接 finished () 信号到 QObject::deleteLater ().

使用 wait () 去阻塞调用线程,直到其它线程已执行完成 (或直到指定时间已过去)。

QThread 还提供独立于平台的静态休眠函数: sleep (), msleep (),和 usleep () 分别允许完整秒、毫秒及微秒分辨率。这些函数是在 Qt 5.0 公开的。

注意: wait () 和 sleep () 函数通常是不必要的,因为 Qt 是事件驱动型框架。代替 wait (),考虑监听 finished () 信号。代替 sleep () 函数,考虑使用 QTimer .

静态函数 currentThreadId () 和 currentThread () 返回目前正执行线程的标识符。前者返回特定平台线程 ID。后者返回 QThread 指针。

要选择给予线程的名称 (作为标识通过命令 ps -L 例如在 Linux),可以调用 setObjectName() 在启动线程之前。若不调用 setObjectName() ,给予线程的名称将是线程对象 Runtime (运行时) 类型的类名 (例如: "RenderThread" 在案例 Mandelbrot 范例 ,因为那是 QThread 子类的名称)。注意:这目前不可用于发行 Windows 构建。

另请参阅 Qt 中的线程支持 , QThreadStorage , 同步线程 , Mandelbrot 范例 , 信号量范例 ,和 等待条件范例 .

成员类型文档编制

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 使用如创建线程的相同优先级。这是默认。

成员函数文档编制

QThread:: QThread ( QObject * parent = nullptr)

构造新的 QThread 去管理新线程。 parent 拥有 QThread 的所有权。线程不会被执行直到 start () 被调用。

另请参阅 start ().

[private signal] void QThread:: finished ()

此信号被发射,从关联线程正好完成执行之前。

当发射此信号时,事件循环已停止运行。线程中没有更多要处理事件,除延期删除事件外。此信号可以连接到 QObject::deleteLater (),去释放在该线程中的对象。

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

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

另请参阅 started ().

[slot] void QThread:: quit ()

告诉线程的事件循环采用返回代码 0 (成功) 退出。相当于调用 QThread::exit (0).

此函数什么都不做,若线程没有事件循环。

注意: 此函数是 thread-safe .

另请参阅 exit () 和 QEventLoop .

[slot] void QThread:: start ( QThread::Priority priority = InheritPriority)

开始执行线程通过调用 run ()。操作系统将调度线程根据 priority 参数。若线程已经在运行,此函数什么都不做。

作用为 priority 参数从属于操作系统的调度策略。尤其, priority 会被忽略,在不支持线程优先级的系统中 (如在 Linux,见 sched_setscheduler 文档编制了解更多细节)。

另请参阅 run () 和 terminate ().

[private signal] void QThread:: started ()

此信号被发射当关联线程开始执行时,前于 run () 函数被调用。

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

另请参阅 finished ().

[slot] void QThread:: terminate ()

终止线程的执行。线程可能 (或不可能) 被立即终止,取决于操作系统的调度策略。使用 QThread::wait () 在 terminate() 之后,来确保。

当线程被终止时,等待线程完成的所有线程都将被唤醒。

警告: 此函数是危险的,且不鼓励使用。线程可以在其代码路径中的任何点被终止。线程可以被终止,当修改数据时。线程没有机会在本身、解锁任何保持互斥、等之后被清理。简而言之,若绝对有必要才使用此函数。

终止可以被明确启用 (或禁用) 通过调用 QThread::setTerminationEnabled ()。当终止被禁用时,调用此函数会导致终止被延期,直到终止被重新启用。见文档编制 QThread::setTerminationEnabled () 了解更多信息。

注意: 此函数是 thread-safe .

另请参阅 setTerminationEnabled ().

[virtual] QThread:: ~QThread ()

销毁 QThread .

注意:删除 QThread 对象不会停止其管理的线程的执行。删除正运行 QThread (i.e. isFinished () 返回 false ) 会导致程序崩溃。等待 finished () 信号先于删除 QThread .

[static, since 5.10] template <typename Function, typename Args> QThread *QThread:: create ( Function && f , Args &&... args )

创建新的 QThread 对象将执行函数 f 采用自变量 args .

新线程未被启动 -- 它必须被启动通过明确调用 start ()。这允许连接到其信号、把 QObject 移动到线程、选择新线程的优先级、等等。函数 f 将在新线程中被调用。

返回新近创建 QThread 实例。

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

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

该函数在 Qt 5.10 引入。

另请参阅 start ().

[static] QThread *QThread:: currentThread ()

返回指针指向 QThread 其管理目前正执行线程。

[static] Qt::HANDLE QThread:: currentThreadId ()

返回目前执行线程的线程句柄。

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

注意: 在 Windows,此函数返回由 Win32 函数 GetCurrentThreadId() 返回的 DWORD (Windows-Thread ID),而不是由 Win32 函数 GetCurrentThread() 返回的伪 HANDLE (Windows-Thread HANDLE)。

[override virtual] bool QThread:: event ( QEvent * event )

重实现: QObject::event (QEvent *e).

[since 5.0] QAbstractEventDispatcher *QThread:: eventDispatcher () const

返回指针指向线程的事件分派程序对象。若线程不存在事件分派程序,此函数返回 nullptr .

该函数在 Qt 5.0 引入。

另请参阅 setEventDispatcher ().

[protected] int QThread:: exec ()

进入事件循环并等待,直到 exit () 被调用,返回值被传递给 exit ()。返回值为 0 若 exit () 被调用凭借 quit ().

此函数意味着被调用从 run ()。它是必要的,去调用此函数以开始事件处理。

注意: 这只可以在线程本身内被调用,即:当它是当前线程时。

另请参阅 quit () 和 exit ().

void QThread:: exit ( int returnCode = 0)

告诉线程的事件循环采用返回代码退出。

在调用此函数之后,线程离开事件循环并返回从调用 QEventLoop::exec ()。 QEventLoop::exec () 函数返回 returnCode .

按约定, returnCode 0 意味着成功,任何非零值指示出错。

注意:不像同名 C 库函数,此函数 does 返回给调用者 -- 它停止事件处理。

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

注意: 此函数是 thread-safe .

另请参阅 quit () 和 QEventLoop .

[static] int QThread:: idealThreadCount ()

返回可以在系统中运行的理想线程数。这是通过查询系统中实际和逻辑处理器核心数来完成的。此函数返回 1,若无法检测处理器核心数。

bool QThread:: isFinished () const

返回 true 若线程已完成;否则返回 false .

注意: 此函数是 thread-safe .

另请参阅 isRunning ().

[since 5.2] bool QThread:: isInterruptionRequested () const

返回 true,若在此线程中正运行的任务应被停止。中断可以被请求通过 requestInterruption ().

此函数可以被用于使长时间运行的任务能完全中断。从不检查 (或处理) 由此函数返回的值是安全的,不管怎样,建议在长时间运行函数中定期这样做。当心不要太频繁调用它,以保持较低开销。

void long_task() {
     forever {
        if ( QThread::currentThread()->isInterruptionRequested() ) {
            return;
        }
    }
}
							

注意: 这只可以在线程本身内被调用,即:当它是当前线程时。

该函数在 Qt 5.2 引入。

另请参阅 currentThread () 和 requestInterruption ().

bool QThread:: isRunning () const

返回 true 若线程正在运行;否则返回 false .

注意: 此函数是 thread-safe .

另请参阅 isFinished ().

[since 5.5] int QThread:: loopLevel () const

返回线程的当前事件循环级别。

注意: 这只可以在线程本身内被调用,即:当它是当前线程时。

该函数在 Qt 5.5 引入。

[static] void QThread:: msleep ( unsigned long msecs )

强制当前线程休眠 msecs 毫秒。

避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).

注意: 此函数不保证准确性。应用程序可能休眠超过 msecs 在重负载条件下。某些 OS (操作系统) 可能圆整 msecs up to 10 ms or 15 ms.

另请参阅 sleep () 和 usleep ().

QThread::Priority QThread:: priority () const

返回正运行线程的优先级。若线程未在运行,此函数返回 InheritPriority .

另请参阅 Priority , setPriority (),和 start ().

[since 5.2] void QThread:: requestInterruption ()

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

注意: 此函数是 thread-safe .

该函数在 Qt 5.2 引入。

另请参阅 isInterruptionRequested ().

[virtual protected] void QThread:: run ()

线程的起点。先调用 start (),新近创建的线程调用此函数。默认实现只需调用 exec ().

可以重实现此函数以促进高级线程管理。来自此方法的返回将结束线程的执行。

另请参阅 start () 和 wait ().

[since 5.0] void QThread:: setEventDispatcher ( QAbstractEventDispatcher * eventDispatcher )

把线程的事件分派程序设为 eventDispatcher 。这才是可能的,只要尚未为线程安装事件分派程序。也就是说,在线程被启动之前采用 start (),或在主线程情况下,先于 QCoreApplication 被实例化。此方法拥有对象的所有权。

该函数在 Qt 5.0 引入。

另请参阅 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 ().

void QThread:: setStackSize ( uint stackSize )

把线程的最大堆栈尺寸设为 stackSize 。若 stackSize 大于 0,最大堆栈尺寸被设为 stackSize 字节,否则,最大堆栈尺寸由操作系统自动确定。

警告: 大多数操作系统对线程堆栈尺寸,有最小和最大限制。线程将无法启动,若堆栈尺寸超出这些限制。

另请参阅 stackSize ().

[static protected] void QThread:: setTerminationEnabled ( bool enabled = true)

启用 (或禁用) 当前线程的终止,基于 enabled 参数。线程必须已被启动由 QThread .

enabled 为 false,终止被禁用。未来调用 QThread::terminate () 将立即返回没有效果。相反,终止被延期,直到终止被启用。

enabled 为 true,终止被启用。未来调用 QThread::terminate () 将正常终止线程。若终止已被延期 (即: QThread::terminate () 被调用采用终止被禁用),此函数将终止调用线程 immediately 。注意:此函数不会返回,在此情况下。

另请参阅 terminate ().

[static] void QThread:: sleep ( unsigned long secs )

强制当前线程休眠 secs 秒。

避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).

注意: 此函数不保证准确性。应用程序可能休眠超过 secs 在重负载条件下。

另请参阅 msleep () 和 usleep ().

uint QThread:: stackSize () const

返回线程的最大堆栈尺寸 (若设置采用 setStackSize ());否则返回 0。

另请参阅 setStackSize ().

[static] void QThread:: usleep ( unsigned long usecs )

强制当前线程休眠 usecs 微秒。

避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).

注意: 此函数不保证准确性。应用程序可能休眠超过 usecs 在重负载条件下。某些 OS (操作系统) 可能圆整 usecs 到 10 毫秒 (或 15 毫秒);在 Windows,它会被四舍五入到 1 毫秒的倍数。

另请参阅 sleep () 和 msleep ().

[since 5.15] bool QThread:: wait ( QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))

阻塞线程,直到满足这些条件之一:

  • 关联此线程的 QThread 对象已执行完成 (即:当它返回从 run ())。此函数将返回 true,若线程已完成。它也返回 true,若线程尚未被启动。
  • deadline 到达。此函数将返回 false,若到达 deadline (最后期限)。

deadline (截止日期) 计时器设为 QDeadlineTimer::Forever (默认) 将从不超时:在此情况下,函数才返回当线程返回从 run () 或若线程尚未启动。

这提供的功能类似 POSIX pthread_join() 函数。

该函数在 Qt 5.15 引入。

另请参阅 sleep () 和 terminate ().

bool QThread:: wait ( unsigned long time )

这是重载函数。

[static] void QThread:: yieldCurrentThread ()

把当前线程的执行产生到另一可运行线程,若有的话。注意:操作系统决定切换到哪个线程。