前言
在使用 PySide2 和 Qt Quick 开发应用程序时,如果在程序启动时创建了一个新的线程,并且在关闭主窗口时程序没有退出,这可能是由于后台线程仍在运行,而主线程(GUI 线程)已经退出。
为了确保程序正确退出,需要确保所有后台线程在主窗口关闭时也被妥善处理。
以下是一些可能的解决方案:
设置线程为守护线程
在 Python 中,可以将线程设置为守护线程,这样当主线程退出时,守护线程会自动退出。
1 2 3 4 5 6 7 8 9 10 11
| import threading
def background_task(): while True: pass
background_thread = threading.Thread(target=background_task) background_thread.daemon = True background_thread.start()
|
在主窗口关闭时停止后台线程
如果后台线程需要执行一些清理操作,可以显式地停止后台线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import threading import time
class BackgroundWorker(threading.Thread): def __init__(self): super().__init__() self.stop_event = threading.Event()
def run(self): while not self.stop_event.is_set(): time.sleep(1)
def stop(self): self.stop_event.set()
background_worker = BackgroundWorker() background_worker.start()
def on_close(): background_worker.stop() background_worker.join()
from PySide2.QtWidgets import QApplication from PySide2.QtQml import QQmlApplicationEngine
app = QApplication([]) engine = QQmlApplicationEngine() engine.quit.connect(on_close)
|
使用 QThread
在 Qt 应用程序中,推荐使用 QThread 而不是 Python 的 threading.Thread,因为 QThread 与 Qt 的事件循环更紧密地集成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from PySide2.QtCore import QThread, Signal, Slot
from PySide2.QtWidgets import QApplication from PySide2.QtQml import QQmlApplicationEngine
class BackgroundWorker(QThread): def run(self): while not self.isInterruptionRequested(): self.msleep(1000)
background_worker = BackgroundWorker() background_worker.start()
def on_close(): background_worker.requestInterruption() background_worker.waitForFinished()
app = QApplication([]) engine = QQmlApplicationEngine() engine.quit.connect(on_close)
|
使用 QObject 的析构函数
确保在主窗口关闭时,所有相关的 QObject 对象被正确销毁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| from PySide2.QtCore import QObject, Signal, Slot from PySide2.QtWidgets import QApplication from PySide2.QtQml import QQmlApplicationEngine
class BackgroundWorker(QObject): def __init__(self): super().__init__() self.thread = QThread() self.moveToThread(self.thread) self.thread.started.connect(self.run) self.thread.start()
@Slot() def run(self): while True: time.sleep(1)
def cleanup(self): self.thread.quit() self.thread.wait()
background_worker = BackgroundWorker()
def on_close(): background_worker.cleanup()
app = QApplication([]) engine = QQmlApplicationEngine() engine.quit.connect(on_close)
|
通过以上方法,可以确保在关闭主窗口时,后台线程被正确停止,从而使整个应用程序能够顺利退出。
获取所在线程
1 2 3 4
| import threading
current_thread = threading.current_thread() print(f"Worker thread: {current_thread.name} (ID: {current_thread.ident})")
|