迭代调用函数时QtCore.QTimer.singleShot滞后

时间:2015-08-10 20:51:28

标签: python multithreading pyqt qtimer

我有一些文本显示的pyqt gui,它会通过函数定期更新 updateTelemetry()

以下是我的代码的工作原理。当用户单击该按钮时,将调用buttonHandler。并且每10秒迭代地调用updateTelemetry。:

def buttonHandler(self):
    self.monitor=true
    self.updateTelemetry()

def updateTelemetry(self):
   try:
        #update values on gui
   finally:
       if self.monitor:
          QtCore.QTimer.singleShot(10000, self.updateTelemetry)

这种方法很有效,让我每10秒左右就能得到一次更新。然而,每隔10秒,整个gui冻结几秒钟然后更新。我正在做的事情似乎在阻止。我不确定那是怎么回事。我以为qtimer.singleshot会创建一个单独的线程吗?

有没有更好的方法来做我正在做的事情?

1 个答案:

答案 0 :(得分:1)

QTimer不会创建单独的线程。 QTimer只是在给定的超时后在主线程中发出一个信号。因此,所有内容(包括您的设备读取代码)仍在主线程中运行。

您应该将从设备读取的代码移动到QThread,并从QThread向主线程发出信号,您可以在其中更新GUI。 GUI更新只能从主线程完成。只有信号发射是线程安全的!

以下是QThread的粗略实现。

class MyThread(QObject):
    send_data_to_gui = pyqtSignal(str)

    def __init__(self,*args,**kwargs):
        QObject.__init__(self,*args,**kwargs)

    @pyqtSlot()
    def run(self):
        while True: 
            # get data from device
            self.send_data_to_gui.emit(data_from_device)
            time.sleep(10) 

...

thread = QThread()
my_thread = MyThread()
my_thread.send_data_to_gui.connect(my_slot)
my_thread.moveToThread(thread)
thread.started.connect(my_thread.run)
thread.start()

请注意,在它的当前形式中,QThread实际上拥有它自己的事件循环,因此您可以执行各种复杂的操作(但while True此时正在阻止事件循环)。由于线程具有独立的事件循环,您可以将while True替换为QTimer,配置为每10秒触发一次(确保在线程中实际创建了QTimer。{ {1}}仍然在主线程中运行,但MyThread.__init__的内容将在新线程中执行。您还可能希望添加关闭线程的功能,或添加我不知道的其他功能!

如果您的实施有问题,请随时发布有关堆栈溢出的后续问题!