QThread 类提供独立于平台的方式管理线程。 更多...
头: | #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 |
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
|
使用如创建线程的相同优先级。这是默认。 |
构造新的 QThread 去管理新线程。 parent 拥有 QThread 的所有权。线程不会被执行直到 start () 被调用。
另请参阅 start ().
[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 ().
[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 文档编制了解更多细节)。
[private signal]
void
QThread::
started
()
此信号被发射当关联线程开始执行时,前于 run () 函数被调用。
注意: 这是私有信号。它可以用于信号连接,但不能由用户发射。
另请参阅 finished ().
[slot]
void
QThread::
terminate
()
终止线程的执行。线程可能 (或不可能) 被立即终止,取决于操作系统的调度策略。使用 QThread::wait () 在 terminate() 之后,来确保。
当线程被终止时,等待线程完成的所有线程都将被唤醒。
警告: 此函数是危险的,且不鼓励使用。线程可以在其代码路径中的任何点被终止。线程可以被终止,当修改数据时。线程没有机会在本身、解锁任何保持互斥、等之后被清理。简而言之,若绝对有必要才使用此函数。
终止可以被明确启用 (或禁用) 通过调用 QThread::setTerminationEnabled ()。当终止被禁用时,调用此函数会导致终止被延期,直到终止被重新启用。见文档编制 QThread::setTerminationEnabled () 了解更多信息。
注意: 此函数是 thread-safe .
另请参阅 setTerminationEnabled ().
[虚拟]
QThread::
~QThread
()
销毁 QThread .
注意:删除
QThread
对象不会停止其管理的线程的执行。删除正运行
QThread
(即
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 ()。它是必要的,去调用此函数以开始事件处理。
注意: 只可以在线程自身 (即:当它是当前线程时) 内调用这。
[static]
int
QThread::
idealThreadCount
()
返回可以在系统中运行的理想线程数。这是通过查询系统中实际和逻辑处理器核心数来完成的。此函数返回 1,若无法检测处理器核心数。
返回
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 ().
返回
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 到 10 ms 或 15 ms。
返回正运行线程的优先级。若线程未在运行,此函数返回
InheritPriority
.
另请参阅 Priority , setPriority (),和 start ().
[since 5.2]
void
QThread::
requestInterruption
()
请求线程的中断。该请求是建议性的,且由在线程上运行的代码决定是否以及如何处理此请求。此函数不会停止在线程中运行的任何事件循环,也不会以任何方式终止它。
注意: 此函数是 thread-safe .
该函数在 Qt 5.2 引入。
另请参阅 isInterruptionRequested ().
[virtual protected]
void
QThread::
run
()
线程的起点。先调用 start (),新近创建的线程调用此函数。默认实现只需调用 exec ().
可以重实现此函数以促进高级线程管理。来自此方法的返回将结束线程的执行。
[since 5.0]
void
QThread::
setEventDispatcher
(
QAbstractEventDispatcher
*
eventDispatcher
)
把线程的事件分派程序设为 eventDispatcher 。这才可能,只要尚未为线程安装事件分派程序。也就是说,在启动线程之前采用 start (),或在主线程情况下,先于 QCoreApplication 被实例化。此方法拥有对象的所有权。
该函数在 Qt 5.0 引入。
另请参阅 eventDispatcher ().
此函数设置 priority 为正运行线程。若线程未在运行,此函数什么都不做并立即返回。使用 start () 去启动线程采用特定优先级。
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 ().
[static]
void
QThread::
usleep
(
unsigned
long
usecs
)
强制当前线程休眠 usecs 微秒。
避免使用此函数,若需要等待给定条件改变。相反,可把槽连接到指示改变的信号或使用事件处理程序 (见 QObject::event ()).
注意: 此函数不保证准确性。应用程序可能休眠超过 usecs 在重负载条件下。某些 OS (操作系统) 可能圆整 usecs 到 10 毫秒 (或 15 毫秒);在 Windows,它会被四舍五入到 1 毫秒的倍数。
[since 5.15]
bool
QThread::
wait
(
QDeadlineTimer
deadline
= QDeadlineTimer(QDeadlineTimer::Forever))
阻塞线程,直到满足这些条件之一:
deadline (截止日期) 计时器设为
QDeadlineTimer::Forever
(默认) 将从不超时:在此情况下,函数才返回当线程返回从
run
() 或若线程尚未启动。
这提供的功能类似 POSIX
pthread_join()
函数。
该函数在 Qt 5.15 引入。
这是重载函数。
[static]
void
QThread::
yieldCurrentThread
()
把当前线程的执行产生到另一可运行线程,若有的话。注意:操作系统决定切换到哪个线程。