【问题标题】:In QThread: calls a function again 1 second after the function finishes在QThread中:函数完成后1秒再次调用函数
【发布时间】:2020-11-12 10:44:13
【问题描述】:

我想每1s获取一次光谱仪的光谱,下面是我为此编写的代码。

但是,当光谱仪以低于 1 Hz 的频率触发时, 请求频谱的函数将等待触发并需要超过 1 秒的时间来处理,而计时器已经超时。 这会导致线程非常滞后并最终冻结。

有什么更好的方法来编写它,以便在函数完成自身后调用函数 'acquire_spectrum' 1s,而不是每 1s 调用一次?

class Spec_Thread(QThread):


    def __init__(self):
        QThread.__init__(self)
        self.signals = Signals()
        self.specth = Spectrometer.from_first_available() #connect to the spectrometer
        self.threadtimer = QTimer()
        self.threadtimer.moveToThread(self)
        self.threadtimer.timeout.connect(self.acquire_spectrum)

    def acquire_spectrum(self): #acquire the current spectrum from the spectrometer

        print('in thread,', device_running)
        if device_running == True:
            self.specth.open() #open the usb portal
            self.wavelengths = self.specth.wavelengths() #acquire wavelengths (will wait for a trigger)
            self.intensities = self.specth.intensities() #acquire intensities (will wait for a trigger)
            self.specth.close() #close usb portal
            self.signals.new_spectrum.emit(self.wavelengths, self.intensities)
        else:
            print('Device stopped')
            return



    def run(self):

        self.threadtimer.start(10000)
        loop = QEventLoop()
        loop.exec_()

【问题讨论】:

    标签: python pyqt pyqt5 qthread qtimer


    【解决方案1】:

    你必须在完成任务执行后启动一个计时器,为此你可以threading.Timer()

    import threading
    
    from PyQt5 import QtCore
    
    import numpy as np
    
    from seabreeze.spectrometers import Spectrometer
    
    
    class QSpectrometer(QtCore.QObject):
        dataChanged = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self.specth = Spectrometer.from_first_available()
    
        def start(self, repeat=False):
            threading.Thread(target=self._read, args=(repeat,), daemon=True).start()
    
        def _read(self, repeat):
            self.specth.open()
            wavelengths = self.specth.wavelengths()
            intensities = self.specth.intensities()
            self.specth.close()
            self.dataChanged.emit(wavelengths, intensities)
            if repeat:
                threading.Timer(1, self._read, (repeat,)).start()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtCore.QCoreApplication(sys.argv)
        spectometer = QSpectrometer()
        spectometer.start(True)
        spectometer.dataChanged.connect(print)
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的建议!我忘了提到这将成为 GUI 的一部分,这就是我将所有内容都放在 QThread 中的原因。这个 threading.Timer() 方法在这种情况下仍然有效吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    相关资源
    最近更新 更多