工作线程阻塞 GUI 中的 QTimer
QTimer in worker thread blocking GUI
我正在尝试创建一个工作线程,其工作是监视定位平台的状态位。
为此,我将 QTimer 超时信号连接到查询平台的函数。
class expSignals(QtCore.QObject):
pause=QtCore.pyqtSignal()
class motorpositioner(QtCore.QObject):
def __init__(self):
QtCore.QThread.__init__(self)
self.timer = QtCore.QTimer()
self.timer.start(100)
self.timer.timeout.connect(self.do_it)
self.lock=QtCore.QMutex()
self.running=True
self.stat=0
def do_it(self):
with QtCore.QMutexLocker(self.lock):
#self.stat = self.motors.get_status()
print(self.stat)
time.sleep(5)
@QtCore.pyqtSlot()
def stop1(self):
self.timer.stop()
print('stop heard')
GUI 看起来像这样:
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.thread=QtCore.QThread(self)
#worker
self.mot=motorpositioner()
# =============================================================================
# Putting buttons and GUI stuff in place
# =============================================================================
self.button=QtWidgets.QPushButton('Derp',self)
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
self.setGeometry( 300, 300, 350, 300 )
# =============================================================================
# Connecting signals
# =============================================================================
self.sig=expSignals()
self.sig2=expSignals()
self.button.clicked.connect(self.stop)
self.sig.pause.connect(self.mot.stop1)
self.sig2.pause.connect(self.thread.quit)
self.mot.moveToThread(self.thread)
self.thread.start()
def stop(self):
self.sig.pause.emit()
def closeEvent(self,event):
self.sig2.pause.emit()
event.accept()
然而,它现在的编写方式 GUI 没有响应。但是,如果我注释掉 self.timer.timeout.connect(self.do_it)
并将 do_it
放入 while(True)
循环中,则不会阻止 GUI。
为什么使用QTimer会阻塞主线程?
我不知道什么是 expSignals()
,我认为它不相关,按钮也不相关。
您的代码存在以下错误:
您在线程启动之前启动计时器,因此任务将 运行 在 GUI 线程上。
QTimer
不是 motorpositioner
的 child,因此如果 motorpositioner
移动到新线程 QTimer
则不会。他必须是儿子才能移动,因此您必须将他作为 parent 传给自己。
我不知道这是否是一个真正的错误,但你每 100 毫秒触发一次 QTimer,但任务需要 5 秒,尽管 QMutex 有助于没有问题,因为它被阻止了。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import time
class motorpositioner(QtCore.QObject):
def __init__(self):
QtCore.QThread.__init__(self)
self.timer = QtCore.QTimer(self)
self.lock = QtCore.QMutex()
self.running = True
self.stat = 0
def start_process(self):
self.timer.timeout.connect(self.do_it)
self.timer.start(100)
def do_it(self):
with QtCore.QMutexLocker(self.lock):
#self.stat = self.motors.get_status()
print(self.stat)
time.sleep(5)
@QtCore.pyqtSlot()
def stop1(self):
self.timer.stop()
print('stop heard')
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.thread = QtCore.QThread(self)
self.mot = motorpositioner()
self.mot.moveToThread(self.thread)
self.thread.started.connect(self.mot.start_process)
self.thread.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = MyApp()
ex.show()
sys.exit(app.exec_())
我正在尝试创建一个工作线程,其工作是监视定位平台的状态位。
为此,我将 QTimer 超时信号连接到查询平台的函数。
class expSignals(QtCore.QObject):
pause=QtCore.pyqtSignal()
class motorpositioner(QtCore.QObject):
def __init__(self):
QtCore.QThread.__init__(self)
self.timer = QtCore.QTimer()
self.timer.start(100)
self.timer.timeout.connect(self.do_it)
self.lock=QtCore.QMutex()
self.running=True
self.stat=0
def do_it(self):
with QtCore.QMutexLocker(self.lock):
#self.stat = self.motors.get_status()
print(self.stat)
time.sleep(5)
@QtCore.pyqtSlot()
def stop1(self):
self.timer.stop()
print('stop heard')
GUI 看起来像这样:
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.thread=QtCore.QThread(self)
#worker
self.mot=motorpositioner()
# =============================================================================
# Putting buttons and GUI stuff in place
# =============================================================================
self.button=QtWidgets.QPushButton('Derp',self)
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
self.setGeometry( 300, 300, 350, 300 )
# =============================================================================
# Connecting signals
# =============================================================================
self.sig=expSignals()
self.sig2=expSignals()
self.button.clicked.connect(self.stop)
self.sig.pause.connect(self.mot.stop1)
self.sig2.pause.connect(self.thread.quit)
self.mot.moveToThread(self.thread)
self.thread.start()
def stop(self):
self.sig.pause.emit()
def closeEvent(self,event):
self.sig2.pause.emit()
event.accept()
然而,它现在的编写方式 GUI 没有响应。但是,如果我注释掉 self.timer.timeout.connect(self.do_it)
并将 do_it
放入 while(True)
循环中,则不会阻止 GUI。
为什么使用QTimer会阻塞主线程?
我不知道什么是 expSignals()
,我认为它不相关,按钮也不相关。
您的代码存在以下错误:
您在线程启动之前启动计时器,因此任务将 运行 在 GUI 线程上。
QTimer
不是motorpositioner
的 child,因此如果motorpositioner
移动到新线程QTimer
则不会。他必须是儿子才能移动,因此您必须将他作为 parent 传给自己。我不知道这是否是一个真正的错误,但你每 100 毫秒触发一次 QTimer,但任务需要 5 秒,尽管 QMutex 有助于没有问题,因为它被阻止了。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import time
class motorpositioner(QtCore.QObject):
def __init__(self):
QtCore.QThread.__init__(self)
self.timer = QtCore.QTimer(self)
self.lock = QtCore.QMutex()
self.running = True
self.stat = 0
def start_process(self):
self.timer.timeout.connect(self.do_it)
self.timer.start(100)
def do_it(self):
with QtCore.QMutexLocker(self.lock):
#self.stat = self.motors.get_status()
print(self.stat)
time.sleep(5)
@QtCore.pyqtSlot()
def stop1(self):
self.timer.stop()
print('stop heard')
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.thread = QtCore.QThread(self)
self.mot = motorpositioner()
self.mot.moveToThread(self.thread)
self.thread.started.connect(self.mot.start_process)
self.thread.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = MyApp()
ex.show()
sys.exit(app.exec_())