gpt4 book ai didi

multithreading - PyQt : How to deal with QThread?

转载 作者:行者123 更新时间:2023-12-03 12:59:35 28 4
gpt4 key购买 nike

在以下代码中,我尝试处理QThread。在此可执行示例中,有三个按钮:第一个用于启动,第二个用于停止,第三个用于关闭。好吧,当我开始执行任务时,它的运行就像一个魅力。 但是,当我想停止while循环时,单击,请单击“停止”按钮。而现在,出现了一个问题:while循环不会停止。

您会看到,停止按钮发出信号以调用stop()上的TestTask()方法。

怎么了?

from sys import argv

from PyQt4.QtCore import QObject, pyqtSignal, QThread, Qt, QMutex

from PyQt4.QtGui import QDialog, QApplication, QPushButton, \
QLineEdit, QFormLayout, QTextEdit

class TestTask(QObject):

def __init__(self, parent=None):
QObject.__init__(self, parent)

self._mutex = QMutex()

self._end_loop = True

def init_object(self):
while self._end_loop:
print "Sratus", self._end_loop

def stop(self):
self._mutex.lock()
self._end_loop = False
self._mutex.unlock()

class Form(QDialog):
stop_loop = pyqtSignal()

def __init__(self, parent=None):
QDialog.__init__(self, parent)

self.init_ui()

def init_ui(self):


self.pushButton_start_loop = QPushButton()
self.pushButton_start_loop.setText("Start Loop")

self.pushButton_stop_loop = QPushButton()
self.pushButton_stop_loop.setText("Stop Loop")

self.pushButton_close = QPushButton()
self.pushButton_close.setText("Close")

layout = QFormLayout()

layout.addWidget(self.pushButton_start_loop)
layout.addWidget(self.pushButton_stop_loop)
layout.addWidget(self.pushButton_close)

self.setLayout(layout)
self.setWindowTitle("Tes Window")

self.init_signal_slot_pushButton()

def start_task(self):

self.task_thread = QThread(self)
self.task_thread.work = TestTask()
self.task_thread.work.moveToThread(self.task_thread)
self.task_thread.started.connect(self.task_thread.work.init_object)

self.stop_loop.connect(self.task_thread.work.stop)

self.task_thread.start()

def stop_looping(self):
self.stop_loop.emit()

def init_signal_slot_pushButton(self):

self.pushButton_start_loop.clicked.connect(self.start_task)

self.pushButton_stop_loop.clicked.connect(self.stop_looping)

self.pushButton_close.clicked.connect(self.close)



app = QApplication(argv)
form = Form()
form.show()
app.exec_()

最佳答案

stop_loop信号被转换为事件,并发送到信号接收器的线程。但是您的辅助对象正在运行阻塞的while循环,这可以防止线程在其事件队列中处理任何未决的事件。因此连接到stop_loop信号的插槽将永远不会被调用。

要解决此问题,您可以在while循环中调用processEvents,以允许线程处理其未决事件:

def init_object(self):
while self._end_loop:
QThread.sleep(1)
QApplication.processEvents()
print "Status", self._end_loop

另外,您可以直接调用工作程序的 stop()方法,而不发出信号。严格来说,这不是线程安全的,但是只有多个线程可以同时调用 stop()才是问题。因此,一种更正确的方法是使用互斥锁来保护要更改的值:
class TestTask(QObject):   
def __init__(self, parent=None):
QObject.__init__(self, parent)
self._mutex = QtCore.QMutex()
self._end_loop = True

def stop(self):
self._mutex.lock()
self._end_loop = False
self._mutex.unlock()

现在,直接从主线程调用 stop()是线程安全的。

关于multithreading - PyQt : How to deal with QThread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41947237/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com