PyQt:如何处理QThread?

时间:2017-01-30 23:27:23

标签: multithreading python-2.7 pyqt4 signals-slots qthread

在以下代码中,我尝试处理stop()。在这个可执行的例子中有三个按钮:第一个用于开始,第二个用于停止,第三个用于关闭。好吧,当我开始任务时,它的运行就像一个魅力。 但是当我希望while循环停止时,我点击停止按钮。现在,有一个问题:while循环不会停止。

您会看到,停止按钮会发出一个信号来调用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_() 方法。

有什么问题?

npm update react-stepzilla

1 个答案:

答案 0 :(得分:2)

stop_loop信号被转换为事件并发送到信号接收器的线程。但是您的worker对象正在运行阻塞的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()是线程安全的。