Qt提供了跨平台的线程支持,其中包括线程类、线程安全的事件发布机制以及支持线程间信号槽连接的特性。这些功能可以帮助开发者轻松地开发可移植的多线程Qt应用程序,并有效利用多处理器系统的资源。此外,多线程编程可以提升应用程序的性能和用户体验,因为耗时操作可以在后台线程中执行,避免主线程阻塞。
在现代应用程序开发中,多线程编程变得越来越重要。Qt的线程类基于POSIX线程库,可以轻松地创建、启动和管理线程,并提供同步和互斥机制,避免线程之间的竞争和死锁问题。此外,Qt还提供了线程池、定时器和事件循环等高级特性,以进一步提升多线程应用程序的性能和可靠性。
需要注意的是,开发多线程应用程序需要特别关注线程安全和资源管理问题,以避免可能出现的问题和错误。
目录
1.QThread: Low-Level API with Optional Event Loops
2.QThreadPool and QRunnable: Reusing Threads
3.Qt Concurrent: Using a High-level API
4.WorkerScript: Threading in QML
3.Accessing QObject Subclasses from Other Threads
4.Signals and Slots Across Threads
一、Qt多线程技术
Qt提供了四种不同的方法来实现多线程应用程序。
1.QThread: Low-Level API with Optional Event Loops
QThread 是 Qt 中线程控制的基础。每个 QThread 实例代表并控制一个线程。
QThread 可以直接实例化或子类化。这两者的区别在于:直接实例化 QThread 提供一个属于QThread线程的事件循环,允许在一个辅助线程中调用 QObject 的 signal/slot和事件;子类化 QThread 可以让应用程序在启动事件循环之前初始化新线程,或在没有事件循环的情况下运行代码。
以下是使用PyQt的简单示例代码:
第一个示例是没有事件循环的多线程使用方法
from PyQt5.QtCore import QThread, pyqtSignal
class MyThread(QThread):
finished_signal = pyqtSignal()
def __init__(self):
super().__init__()
def run(self):
# do some work in the background
self.finished_signal.emit()
在这个示例中,我们定义了一个名为MyThread
的子类,重写了run
方法并定义了一个自定义信号finished_signal
,该信号在线程完成后发射。
接下来,我们可以实例化MyThread
并将其启动,例如:
# create a thread instance
thread = MyThread()
# connect the thread's finished signal to a slot
thread.finished_signal.connect(my_slot)
# start the thread
thread.start()
第二个示例是QThread的另一种用法将QtCore.QThread作为管理线程的类,我们应该将需要在这个线程中执行的任务封装在一个QObject子类的实例中,并将这个实例移动到QThread对象所代表的线程中。具体为自己定义一个线程业务类,这个类要继承QObject,在里面实现线程的相关业务逻辑,同时在主界面里实例化这个线程业务类,然后用moveToThread方法移动到QThread管理。
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
class Worker(QObject):
finished = pyqtSignal()
@pyqtSlot()
def do_work(self):
# 在这里编写线程运行的代码
self.finished.emit()
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.worker = Worker()
self.thread = QThread()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.do_work)
self.worker.finished.connect(self.on_finished)
self.thread.start()
def on_finished(self):
# 线程完成时执行的代码
pass
def closeEvent(self, event):
self.thread.quit()
self.thread.wait()
event.accept()
2.QThreadPool and QRunnable: Reusing Threads
频繁创建和销毁线程可能会导致开销增大。为了减少这种开销,可以重复利用现有线程来处理新任务。QThreadPool是可重复使用QThread的集合。
要在QThreadPool的线程中运行代码,需要重新实现QRunnable::run()并实例化子类化的QRunnable。使用QThreadPool::start()将QRunnable放入QThreadPool的运行队列中。当线程可用时,QRunnable::run()中的代码将在该线程中执行。
每个Qt应用程序都有一个全局线程池,可以通过QThreadPool::globalInstance()访问。该全局线程池根据CPU内核数自动维护最优线程数。但是,也可以显式地创建和管理一个单独的QThreadPool。
PyQt代码例子如下:
from PyQt5.QtCore import QRunnable, QT