QThread 类提供独立于平台的方式管理线程。 更多...
头: | #include <QThread> |
CMake: |
find_package(Qt6 REQUIRED COMPONENTS Core)
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 |
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 | exit (int returnCode = 0) |
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 ¶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 槽连接到来自任何对象、任何线程中的任何信号是自由的。跨不同线程连接信号和槽是安全的,得益于机制 队列连接 .
使在单独线程中运行代码的另一方式,是子类化 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
(),赋予线程的名称将是线程对象运行时类型的类名 (例如,
"RenderThread"
在案例
Mandelbrot 范例
,因为那是 QThread 子类的名称)。注意:目前这不可用于 Windows 发行构建。
另请参阅 Qt 中的线程支持 , QThreadStorage , 同步线程 , Mandelbrot 范例 , 信号量范例 ,和 等待条件范例 .
此枚举类型指示操作系统应如何调度新近创建的线程。
常量 | 值 | 描述 |
---|---|---|
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
|
使用如创建线程的相同优先级。这是默认。 |
[explicit]
QThread::
QThread
(
QObject
*
parent
= nullptr)
构造新的 QThread 去管理新线程。 parent 拥有 QThread 的所有权。线程不会被执行直到 start () 被调用。
另请参阅 start ().
[虚拟]
QThread::
~QThread
()
销毁 QThread .
注意:删除
QThread
对象不会停止其管理的线程的执行。删除正运行
QThread
(即
isFinished
() 返回
false
) 会导致程序崩溃。等待
finished
() 信号先于删除
QThread
.
从 Qt 6.3 起,允许删除 QThread 实例创建通过调用 QThread::create () 事件若相应线程仍在运行。在这种情况下,Qt 会把中断请求张贴给该线程 (凭借 requestInterruption ());将要求线程的事件循环 (若有的话) 离开 (凭借 quit ());且会阻塞直到线程完成。
另请参阅 create (), isInterruptionRequested (), exec (),和 quit ().
[static]
template <typename Function, typename Args>
QThread
*QThread::
create
(
Function
&&
f
,
Args
&&...
args
)
创建新的 QThread 对象以执行函数 f 采用自变量 args .
新线程未启动 – 它的启动必须通过明确调用 start ()。这允许连接到其信号、把 QObject 移动到线程、选择新线程的优先级、等等。函数 f 将在新线程中被调用。
返回新近创建的 QThread 实例。
注意: 调用者获得所有权对于返回的 QThread 实例。
警告: 不要调用 start () 在返回的 QThread 实例超过一次;这样做将产生未定义行为。
另请参阅 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).
返回指针指向线程的事件分派程序对象。若线程不存在事件分派程序,此函数返回
nullptr
.
另请参阅 setEventDispatcher ().
[protected]
int
QThread::
exec
()
进入事件循环并等待,直到 exit () 被调用,返回值被传递给 exit ()。返回值为 0 若 exit () 被调用凭借 quit ().
此函数意味着被调用从 run ()。它是必要的,去调用此函数以开始事件处理。
注意: 只可以在线程自身 (即:当它是当前线程时) 内调用这。
[slot]
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 .
[private signal]
void
QThread::
finished
()
从关联线程发射此信号,在刚好完成线程执行前。
当发射此信号时,事件循环已停止运行。线程没有更多要处理的事件,除延期删除事件外。可以将此信号连接到 QObject::deleteLater (),以释放该线程中的对象。
注意: 若关联线程的终止是使用 terminate (),从哪个线程发出此信号就是未定义的。
注意: 这是私有信号。它可以用于信号连接,但不能由用户发射。
另请参阅 started ().
[static]
int
QThread::
idealThreadCount
()
返回此进程可以并行运行的理想线程数。这是通过查询该进程的可用逻辑处理器数 (若 OS 支持) 或系统逻辑处理器的总数做到的。此函数返回 1,若值无法确定。
注意: 在支持将线程的倾向性设为所有逻辑处理器子集的操作系统,由此函数返回的值可能随线程和时间改变。
注意: 在支持 CPU 热插拔的操作系统,由此函数返回的值也可能随时间改变 (注意,CPU 可以通过软件打开和关闭,不用改变物理硬件)。
返回
true
若线程已完成;否则返回
false
.
注意: 此函数是 thread-safe .
另请参阅 isRunning ().
返回 true,若在此线程中正运行的任务应被停止。中断可以被请求通过 requestInterruption ().
此函数可以用于使长时间运行的任务完全中断。从不检查 (或处理) 由此函数返回的值是安全的,不管怎样,建议在长时间运行函数中定期这样做。当心不要太频繁调用它,以保持较低开销。
void long_task() { forever { if ( QThread::currentThread()->isInterruptionRequested() ) { return; } } }
注意: 只可以在线程自身 (即:当它是当前线程时) 内调用这。
另请参阅 currentThread () 和 requestInterruption ().
返回
true
若线程正在运行;否则返回
false
.
注意: 此函数是 thread-safe .
另请参阅 isFinished ().
返回线程的当前事件循环级别。
注意: 只可以在线程自身 (即:当它是当前线程时) 内调用这。
[static]
void
QThread::
msleep
(
unsigned
long
msecs
)
强制当前线程休眠 msecs 毫秒。
避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).
注意: 此函数不保证准确性。应用程序可能休眠超过 msecs 在重负载条件下。某些 OS (操作系统) 可能圆整 msecs 到 10 ms 或 15 ms。
返回正运行线程的优先级。若线程未在运行,此函数返回
InheritPriority
.
另请参阅 Priority , setPriority (),和 start ().
[slot]
void
QThread::
quit
()
告诉线程的事件循环采用返回代码 0 (成功) 退出。相当于调用 QThread::exit (0).
此函数什么都不做,若线程没有事件循环。
注意: 此函数是 thread-safe .
另请参阅 exit () 和 QEventLoop .
请求线程的中断。该请求是建议性的,且由在线程上运行的代码决定是否以及如何处理此请求。此函数不会停止在线程中运行的任何事件循环,也不会以任何方式终止它。
注意: 此函数是 thread-safe .
另请参阅 isInterruptionRequested ().
[virtual protected]
void
QThread::
run
()
线程的起点。先调用 start (),新近创建的线程调用此函数。默认实现只需调用 exec ().
可以重实现此函数以促进高级线程管理。来自此方法的返回将结束线程的执行。
把线程的事件分派程序设为 eventDispatcher 。这才可能,只要尚未为线程安装事件分派程序。
事件调度程序是自动创建的对于主线程当 QCoreApplication 被实例化且当 start () 对于辅助线程。
此方法拥有对象的所有权。
另请参阅 eventDispatcher ().
此函数设置 priority 为正运行线程。若线程未在运行,此函数什么都不做并立即返回。使用 start () 去启动线程采用特定优先级。
The
priority
自变量可以是任意值在
QThread::Priority
枚举除了
InheritPriority
.
作用为 priority 参数从属于操作系统的调度策略。尤其, priority 会被忽略,在不支持线程优先级的系统中 (如在 Linux,见 http://linux.die.net/man/2/sched_setscheduler 了解更多细节)。
另请参阅 Priority , priority (),和 start ().
把线程的最大堆栈尺寸设为 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 在重负载条件下。
返回线程的最大堆栈尺寸 (若设置采用 setStackSize ());否则返回 0。
另请参阅 setStackSize ().
[slot]
void
QThread::
start
(
QThread::Priority
priority
= InheritPriority)
开始执行线程通过调用 run ()。操作系统将调度线程根据 priority 参数。若线程已经在运行,此函数什么都不做。
作用为 priority 参数从属于操作系统的调度策略。尤其, priority 会被忽略,在不支持线程优先级的系统中 (如在 Linux,见 sched_setscheduler 文档编制了解更多细节)。
[private signal]
void
QThread::
started
()
此信号被发射当关联线程开始执行时,前于 run () 函数被调用。
注意: 这是私有信号。它可以用于信号连接,但不能由用户发射。
另请参阅 finished ().
[slot]
void
QThread::
terminate
()
终止线程的执行。线程可能 (或不可能) 被立即终止,取决于操作系统的调度策略。使用 QThread::wait () 在 terminate() 之后,来确保。
当线程被终止时,等待线程完成的所有线程都将被唤醒。
警告: 此函数是危险的,且不鼓励使用。线程可以在其代码路径中的任何点被终止。线程可以被终止,当修改数据时。线程没有机会在本身、解锁任何保持互斥、等之后被清理。简而言之,若绝对有必要才使用此函数。
终止可以被明确启用 (或禁用) 通过调用 QThread::setTerminationEnabled ()。当终止被禁用时,调用此函数会导致终止被延期,直到终止被重新启用。见文档编制 QThread::setTerminationEnabled () 了解更多信息。
注意: 此函数是 thread-safe .
另请参阅 setTerminationEnabled ().
[static]
void
QThread::
usleep
(
unsigned
long
usecs
)
强制当前线程休眠 usecs 微秒。
避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).
注意: 此函数不保证准确性。应用程序可能休眠超过 usecs 在重负载条件下。某些 OS (操作系统) 可能圆整 usecs 到 10 毫秒 (或 15 毫秒);在 Windows,它会被四舍五入到 1 毫秒的倍数。
阻塞线程,直到满足这些条件之一:
deadline (截止日期) 计时器设为
QDeadlineTimer::Forever
(默认) 将从不超时:在此情况下,函数才返回当线程返回从
run
() 或若线程尚未启动。
这提供的功能类似 POSIX
pthread_join()
函数。
这是重载函数。
time 是要等待的时间 (以毫秒为单位)。若 time 为 ULONG_MAX,则等待从不超时。
[static]
void
QThread::
yieldCurrentThread
()
把当前线程的执行产生到另一可运行线程,若有的话。注意:操作系统决定切换到哪个线程。