我是使用 PySide6 进行 UI 开发的初学者,但由于某些情况,我必须为我创建的程序设计 UI。在此 UI 的一个窗口中,我有一个名为 Worker 的 QObject,它执行一个长时间运行的进程。我在一个名为 CLD 的类中单独定义了工作线程的 UI。这是我的初始化:
class CLD(QWidget):
back_signal = Signal()
def __init__(self, question,threshold = 0.85, verbose = True):
super(CLD, self).__init__()
self.question = question
self.threshold = threshold
self.verbose = verbose
self.setWindowTitle("CLD Generator")
self.input_area = QTextEdit(self)
self.input_area.setMinimumHeight(50)
self.input_area.setMaximumHeight(100)
self.input_area.setReadOnly(True)
self.display_area = QTextEdit(self)
self.display_area.setMinimumHeight(200)
self.display_area.setReadOnly(True)
self.user_input = ""
self.init_ui()
self.worker = Worker(self, self.question, self.threshold, self.verbose)
self.thread = QThread()
self.worker.moveToThread(self.thread)
self.worker.finished.connect(self.on_finished)
self.worker.update_text.connect(self.display_area.append)
self.worker.get_choice.connect(self.enter_choice)
self.thread.started.connect(self.worker.generate)
self.mutex = QMutex()
self.condition = QWaitCondition()
如您所见,我将工作线程移至我在 CLD 类本身中定义的 QThread。长时间运行的进程是工作类中的一个函数,称为generate()。我想在 CLD 类中定义一个“后退”按钮,按下该按钮时,将中止长时间运行的进程的执行,并返回到上一个窗口。为此,我定义了一个这样的函数:
@Slot(str)
def on_finished(self, response):
self.display_area.append(response)
self.run_button.setEnabled(True)
self.thread.quit()
self.thread.wait()
问题是,当我尝试 quit() 时,线程/长时间运行的进程实际上并没有退出。当我使用 thread.wait() 时,UI 完全冻结,无论我等待多久,它都保持不变。当我强制关闭 UI 时,我收到此错误“QThread:线程仍在运行时被破坏”,这显然意味着线程根本没有退出。我想我在这里做错了什么。也许 QThread 连接到主 UI,这样当我调用 quit() 时它实际上并没有退出,因为 UI 仍在运行?任何建议将不胜感激。
目前在代码中,back_signal(应该在按下后退按钮时发出)未连接到 on_finished(),因为我正在测试几件事,但在正常情况下它连接到 on_finished()
我通过完全放弃 QThreads 解决了这个问题。我改为使用 python 中的
threading
模块在工作线程中引发异常。我确保使用单独的线程(我们称之为监视线程)来引发异常。一旦单击“后退”按钮,它就会向监视器线程发出一个信号,该信号立即在工作线程中引发异常。然后我调用 thread.join()
等待它终止。这个过程比简单地调用 QThreads.quit()
和 QThreads.wait()
要快得多。我不知道为什么会这样。如果有人可以详细说明这一点并验证我的方法,我将不胜感激!