工作线程阻塞 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_())