在 QThread 中:函数完成后 1 秒再次调用函数

In QThread: calls a function again 1 second after the function finishes

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

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

有什么更好的编写方法,使其在函数完成后 'acquire_spectrum' 1 秒调用函数,而不是每隔 1 秒调用一次?

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_()

你必须在完成任务执行后启动一个计时器,为此你可以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_())