PySide6.QtCore.QThread¶
- class QThread¶
QThread
类提供了一种平台无关的方式来管理线程。更多…概要¶
方法¶
def
__init__()
def
exec()
def
exec_()
def
isFinished()
def
isRunning()
def
loopLevel()
def
priority()
def
setPriority()
def
setStackSize()
def
stackSize()
def
wait()
虚拟方法¶
def
run()
插槽¶
def
exit()
def
quit()
def
start()
def
terminate()
信号¶
def
finished()
def
started()
静态函数¶
def
currentThread()
def
isMainThread()
def
msleep()
def
sleep()
def
usleep()
注意
本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。
详细描述¶
警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
一个
QThread
对象管理程序中的一个控制线程。QThreads 在run()
中开始执行。默认情况下,run()
通过调用exec()
启动事件循环,并在线程内运行一个 Qt 事件循环。你可以通过使用
moveToThread()
将工作对象移动到线程中来使用它们。class Worker(QObject): Q_OBJECT # public slots def doWork(parameter): result = QString() /* ... here is the expensive or blocking operation ... */ resultReady.emit(result) # signals def resultReady(result): class Controller(QObject): Q_OBJECT workerThread = QThread() # public Controller() { worker = Worker() worker.moveToThread(workerThread) workerThread.finished.connect(worker.deleteLater) self.operate.connect(worker.doWork) worker.resultReady.connect(self.handleResults) workerThread.start() ~Controller() { workerThread.quit() workerThread.wait() # public slots def handleResults(): # signals def operate():
Worker的槽中的代码将在单独的线程中执行。然而,您可以自由地将Worker的槽连接到任何线程中的任何对象的任何信号。由于一种称为
queued connections
的机制,跨不同线程连接信号和槽是安全的。另一种使代码在单独线程中运行的方法是子类化
QThread
并重新实现run()
。例如:class WorkerThread(QThread): Q_OBJECT def run(): result = QString() /* ... here is the expensive or blocking operation ... */ resultReady.emit(result) # signals def resultReady(s): def startWorkInAThread(self): workerThread = WorkerThread(self) workerThread.resultReady.connect(self.handleResults) workerThread.finished.connect(workerThread.deleteLater) workerThread.start()
在那个例子中,线程将在运行函数返回后退出。除非你调用
exec()
,否则线程中不会有任何事件循环运行。重要的是要记住,
QThread
实例存在于
实例化它的旧线程中,而不是调用run()
的新线程中。这意味着所有QThread
的排队槽和调用的方法
都将在旧线程中执行。因此,希望在新线程中调用槽的开发者必须使用工作对象方法;新的槽不应直接实现在子类化的QThread
中。与排队的槽或调用的方法不同,直接在
QThread
对象上调用的方法将在调用该方法的线程中执行。当子类化QThread
时,请记住构造函数在旧线程中执行,而run()
在新线程中执行。如果从这两个函数中访问成员变量,则该变量将从两个不同的线程中访问。请确保这样做是安全的。注意
在与不同线程中的对象交互时必须小心。一般来说,函数只能从创建
QThread
对象本身的线程中调用(例如setPriority()
),除非文档另有说明。详情请参见同步线程。管理线程¶
QThread
会在线程started()
和finished()
时通过信号通知你,或者你可以使用isFinished()
和isRunning()
来查询线程的状态。你可以通过调用
exit()
或quit()
来停止线程。在极端情况下,你可能想要强制terminate()
一个正在执行的线程。然而,这样做是危险的,并且不推荐。请阅读terminate()
和setTerminationEnabled()
的文档以获取详细信息。当线程结束时,您通常希望释放线程中的对象。为此,将
finished()
信号连接到deleteLater()
。使用
wait()
来阻塞调用线程,直到其他线程完成执行(或直到指定的时间过去)。QThread
还提供了静态的、平台独立的睡眠函数:sleep()
、msleep()
和usleep()
分别允许全秒、毫秒和微秒的分辨率。注意
wait()
和sleep()
函数在一般情况下应该是不必要的,因为 Qt 是一个事件驱动的框架。与其使用wait()
,不如考虑监听finished()
信号。与其使用sleep()
函数,不如考虑使用QChronoTimer
。静态函数
currentThreadId()
和currentThread()
返回当前执行线程的标识符。前者返回线程的平台特定ID;后者返回一个QThread
指针。要选择线程的名称(例如在Linux上通过命令
ps -L
识别),你可以在启动线程之前调用setObjectName()
。如果你不调用setObjectName()
,线程的名称将是线程对象运行时类型的类名(例如,在Mandelbrot示例中为"RenderThread"
,因为这是QThread
子类的名称)。请注意,目前在Windows的发布版本中不可用。另请参阅
QThreadStorage
Mandelbrot 使用信号量的生产者和消费者 使用等待条件的生产者和消费者- class Priority¶
此枚举类型指示操作系统应如何调度新创建的线程。
常量
描述
QThread.IdlePriority
仅在没有任何其他线程运行时调度。
QThread.LowestPriority
比LowPriority更少被调度。
QThread.LowPriority
调度频率低于NormalPriority。
QThread.NormalPriority
操作系统的默认优先级。
QThread.HighPriority
比NormalPriority更频繁地调度。
QThread.HighestPriority
比高优先级更频繁地调度。
QThread.TimeCriticalPriority
尽可能频繁地调度。
QThread.InheritPriority
使用与创建线程相同的优先级。这是默认设置。
构造一个新的
QThread
来管理一个新线程。parent
拥有QThread
的所有权。线程在调用start()
之前不会开始执行。另请参阅
返回一个指向
QThread
的指针,该指针管理当前正在执行的线程。- eventDispatcher()¶
- Return type:
返回指向线程的事件分发器对象的指针。如果线程没有事件分发器,此函数返回
None
。另请参阅
- exec()¶
- Return type:
整数
进入事件循环并等待直到调用
exit()
,返回传递给exit()
的值。如果通过quit()
调用exit()
,则返回的值为0。此函数旨在从
run()
内部调用。必须调用此函数以启动事件处理。- exec_()¶
- Return type:
整数
- exit([retcode=0])¶
- Parameters:
retcode – int
告诉线程的事件循环以返回代码退出。
调用此函数后,线程将离开事件循环并从
exec()
调用中返回。exec()
函数返回returnCode
。按照惯例,
returnCode
为 0 表示成功,任何非零值表示错误。请注意,与同名的C库函数不同,此函数确实会返回到调用者——停止的是事件处理。
在这个线程中,直到再次调用
exec()
之前,不会再启动任何QEventLoops。如果exec()
中的事件循环没有运行,那么下一次调用exec()
也会立即返回。另请参阅
- finished()¶
此信号在关联线程即将完成执行时发出。
当发出此信号时,事件循环已经停止运行。除了延迟删除事件外,线程中将不再处理更多事件。此信号可以连接到
deleteLater()
,以释放该线程中的对象。- static idealThreadCount()¶
- Return type:
整数
返回此进程可以并行运行的最佳线程数。这是通过查询此进程可用的逻辑处理器数量(如果此操作系统支持)或系统中逻辑处理器的总数来完成的。如果无法确定这两个值,则此函数返回1。
注意
在支持将线程的亲和性设置为所有逻辑处理器子集的操作系统上,此函数返回的值可能会在线程之间和随时间变化。
注意
在支持CPU热插拔和热拔插的操作系统上,此函数返回的值也可能随时间变化(请注意,CPU可以通过软件开启和关闭,而无需物理硬件更改)。
- isCurrentThread()¶
- Return type:
布尔
如果此线程是
currentThread
,则返回true。另请参阅
currentThreadId()
- isFinished()¶
- Return type:
布尔
如果线程已完成,则返回
true
;否则返回false
。另请参阅
- isInterruptionRequested()¶
- Return type:
布尔
如果在此线程上运行的任务应停止,则返回true。可以通过
requestInterruption()
请求中断。此函数可用于使长时间运行的任务能够干净地中断。从不检查或处理此函数返回的值是安全的,但建议在长时间运行的函数中定期执行此操作。注意不要过于频繁地调用它,以保持开销较低。
void long_task() { forever { if ( QThread::currentThread()->isInterruptionRequested() ) { return; } } }
- static isMainThread()¶
- Return type:
布尔
返回当前执行的线程是否是主线程。
主线程是创建
QCoreApplication
的线程。这通常是调用main()
函数的线程,但不一定如此。它是处理GUI事件的线程,并且可以在其中创建图形对象(QWindow, QWidget)。- isRunning()¶
- Return type:
布尔
如果线程正在运行,则返回
true
;否则返回false
。另请参阅
- loopLevel()¶
- Return type:
整数
返回线程的当前事件循环级别。
注意
这只能在线程本身内部调用,即当它是当前线程时。
- static msleep(msecs)¶
- Parameters:
msecs – 整数
这是一个重载函数,等同于调用:
QThread::sleep(std::chrono::milliseconds{msecs});
返回正在运行的线程的优先级。如果线程没有运行,此函数返回
InheritPriority
。另请参阅
- quit()¶
告诉线程的事件循环以返回代码0(成功)退出。相当于调用
exit
(0)。如果线程没有事件循环,此函数不执行任何操作。
另请参阅
- requestInterruption()¶
请求中断线程。该请求是建议性的,由线程上运行的代码决定是否以及如何对此类请求采取行动。此函数不会停止线程上运行的任何事件循环,也不会以任何方式终止它。
- run()¶
线程的起点。在调用
start()
后,新创建的线程会调用此函数。默认实现仅调用exec()
。您可以重新实现此函数以促进高级线程管理。从该方法返回将结束线程的执行。
- setEventDispatcher(eventDispatcher)¶
- Parameters:
eventDispatcher –
QAbstractEventDispatcher
将线程的事件调度器设置为
eventDispatcher
。这只有在尚未为线程安装事件调度器时才可能实现。当
QCoreApplication
被实例化时,主线程的事件分发器会自动创建,并且在辅助线程的start()
时也会创建。此方法获取对象的所有权。
另请参阅
此函数为正在运行的线程设置
priority
。如果线程未运行,此函数不执行任何操作并立即返回。使用start()
以特定优先级启动线程。priority
参数可以是QThread::Priority
枚举中的任何值,除了InheritPriority
。priority
参数的效果取决于操作系统的调度策略。特别是,在不支持线程优先级的系统上(例如在 Linux 上,详见 http://linux.die.net/man/2/sched_setscheduler),priority
将被忽略。另请参阅
- setStackSize(stackSize)¶
- Parameters:
stackSize – int
设置线程的堆栈大小为
stackSize
。如果stackSize
为零,操作系统或运行时将选择一个默认值。否则,线程的堆栈大小将设置为提供的值(可能会向上或向下取整)。在大多数操作系统上,分配给栈服务的内存量最初会小于
stackSize
,并且会随着线程使用栈而增长。此参数设置它允许增长到的最大大小(即,它设置栈允许占用的虚拟内存空间的大小)。此函数只能在线程启动之前调用。
- static setTerminationEnabled([enabled=true])¶
- Parameters:
enabled – 布尔值
根据
enabled
参数启用或禁用当前线程的终止。该线程必须由QThread
启动。当
enabled
为false时,终止功能被禁用。未来调用terminate()
将立即返回而不产生效果。相反,终止将被推迟,直到启用终止功能。当
enabled
为 true 时,终止功能被启用。未来对terminate()
的调用将正常终止线程。如果终止已被推迟(即terminate()
在禁用终止的情况下被调用),此函数将 立即 终止调用线程。请注意,在这种情况下,此函数不会返回。另请参阅
- static sleep(secs)¶
- Parameters:
秒数 – 整数
强制当前线程休眠
secs
秒。这是一个重载函数,等同于调用:
- stackSize()¶
- Return type:
整数
返回线程的最大堆栈大小(如果使用
setStackSize()
设置);否则返回零。另请参阅
通过调用
run()
开始执行线程。操作系统将根据priority
参数调度线程。如果线程已经在运行,此函数不执行任何操作。priority
参数的效果取决于操作系统的调度策略。特别是,在不支持线程优先级的系统上(例如在Linux上,更多详情请参阅sched_setscheduler文档),priority
将被忽略。另请参阅
- started()¶
当关联线程开始执行时,会发出此信号,因此任何连接到它的槽可能会通过排队调用来调用。尽管事件可能在调用
run()
之前已经发布,但信号的任何跨线程传递可能仍然处于挂起状态。另请参阅
- terminate()¶
终止线程的执行。线程可能会立即终止,也可能不会立即终止,这取决于操作系统的调度策略。在terminate()之后使用
wait()
,以确保线程终止。当线程终止时,所有等待该线程完成的线程将被唤醒。
警告
此函数是危险的,不鼓励使用。线程可以在其代码路径的任何点被终止。线程在修改数据时可能会被终止。线程没有机会自行清理、解锁持有的互斥锁等。简而言之,只有在绝对必要时才使用此函数。
可以通过调用
setTerminationEnabled()
来显式启用或禁用终止。在禁用终止时调用此函数会导致终止被推迟,直到重新启用终止。有关更多信息,请参阅setTerminationEnabled()
的文档。- static usleep(usecs)¶
- Parameters:
usecs – int
这是一个重载函数,等同于调用:
QThread::sleep(std::chrono::microseconds{secs});
注意
此函数不保证准确性。在重负载条件下,应用程序可能会睡眠比
usecs
更长的时间。某些操作系统可能会将usecs
四舍五入到10毫秒或15毫秒;在Windows上,它将被四舍五入到1毫秒的倍数。- wait([deadline=QDeadlineTimer(QDeadlineTimer.Forever)])¶
- Parameters:
截止日期 –
QDeadlineTimer
- Return type:
布尔
阻塞线程,直到满足以下任一条件:
设置为
QDeadlineTimer::Forever
(默认值)的截止时间计时器将永远不会超时:在这种情况下,函数只有在线程从run()
返回时才会返回,或者如果线程尚未启动。这提供了与POSIX
pthread_join()
函数类似的功能。另请参阅
- wait(time)
- Parameters:
时间 – int
- Return type:
布尔
这是一个重载函数。
time
是等待的时间,以毫秒为单位。如果time
是 ULONG_MAX,那么等待将永远不会超时。- static yieldCurrentThread()¶
将当前线程的执行权让给另一个可运行的线程(如果有的话)。请注意,操作系统决定切换到哪个线程。