【问题标题】:QTimer in worker thread blocking GUI工作线程阻塞 GUI 中的 QTimer
【发布时间】:2018-12-20 17:11:25
【问题描述】:

我正在尝试创建一个工作线程,其工作是监视定位平台的状态位。

为此,我将 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
  • sis,为什么我很惊讶你使用 QTimer 而不是 python 附带的标准库线程。不能相信一个框架可以一直工作 请认为这太正常了。
  • 按照这篇文章的建议使用 QTimer 和 QT 线程:link。也不确定如何处理两种类型的线程方法,因为一种方法给了我足够的时间。

标签: python pyqt pyqt5 qthread qtimer


【解决方案1】:

我不知道expSignals() 是什么,我认为它不相关,按钮也不相关。

您的代码有以下错误:

  • 您在线程启动之前启动计时器,因此任务将在 GUI 线程上运行。

  • QTimer 不是motorpositioner 的子级,所以如果motorpositioner 移动到新线程QTimer 不会。为了让他搬家,他必须是儿子,所以你必须把他作为父母传给自己。

  • 我不知道这是否是一个真正的错误,但您每 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_())

【讨论】:

  • 谢谢,将计时器移到孩子身上就行了!还要澄清一下 - 添加了按钮来测试我是否可以从外部停止计时器。 5 秒的睡眠是为了夸大 GUI 冻结,因为我在 100 毫秒内没有注意到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多