5

I'm trying to Pause a QThread and resume it.

So, i have an RFID Reading Loop in the QThread and i want to pause the endless loop when the reader gets an RFID Code. After that, there is a db checking. At the end of the check, i want to resume the RFID Reading Loop to get other codes.

MVCE:

def main():
    global Thread
    app = QtGui.QApplication(sys.argv)
    main = Main()
    Thread = RFID_Thread()
    Thread.rfid_event.connect(Main().on_event)
    Thread.start()
    sys.exit(app.exec_())

class Main(object):
    def __init__(self):
        self.accueil = MainWindow(self)
        self.access = AccessWindow()
        self.accueil.show()

    def on_event(self, data):
        # I WANT TO PAUSE THE QTHREAD HERE

        ###################################
        #   CHECKING DB & SHOWING UI      #
        ###################################

        # AND RESUME IT HERE
class RFID_Thread(QtCore.QThread):
    rfid_event = pyqtSignal(str, name='rfid_event')
    def run(self):
        while 1:
            ser = serial.Serial(port=Serial_Port, baudrate=Serial_Baudrate)
            a = ser.read(19).encode('hex')
            ser.close()
            if len(a) <> 0:
                Code = a[14:]
                self.rfid_event.emit(Code)
                time.sleep(2)

if __name__=='__main__':
    main()

the code can't be reproduced because you need an RFID Reader but we can simulate him by this two lines instead of opening serial port and reading data from it:

a = "**************e20030654408021520403f4b"
time.sleep(4)

I tried to use a status variable but it don't works.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

2 Answers2

5

Finally i've resolved the problem by my self

MVCE:

def main():
    global Thread
    app = QtGui.QApplication(sys.argv)
    main = Main()
    Thread = RFID_Thread()
    Thread.rfid_event.connect(Main().on_event)
    Thread.start()
    sys.exit(app.exec_())

class Main(object):
    def __init__(self):
        self.accueil = MainWindow(self)
        self.access = AccessWindow()
        self.accueil.show()

    def on_event(self, data):
        # I WANT TO PAUSE THE QTHREAD HERE

        Thread.Pause = False
        ###################################
        #   CHECKING DB & SHOWING UI      #
        ###################################

        # AND RESUME IT HERE
        Thread.Pause = True
class RFID_Thread(QtCore.QThread):
    rfid_event = pyqtSignal(str, name='rfid_event')
    Pause = True
    def run(self):
        while 1:
            if Pause:
                  ser = serial.Serial(port=Serial_Port, baudrate=Serial_Baudrate)
                  a = ser.read(19).encode('hex')
                  ser.close()
                  if len(a) <> 0:
                         Code = a[14:]
                         self.rfid_event.emit(Code)
                         time.sleep(2)
            else:
                  continue
 if __name__=='__main__':
    main()

Finally, the State variable was the solution !!

  • I suggest you use mutex for your Pause variable. You are basically accessing it (writing to it on top of that) from your Main object which resides in the main thread of your Qt application - a different thread from your RFID_Thread. Also I advise you to use a QObject instead of subclassing QThread since according to the official documentation doing that should only be in cases where you want to extend the functionality provided by QThread itself. I'm also currently migrating to QObject and it's a pain in the bum but the right thing to do nonetheless. – rbaleksandar Jan 18 '16 at 10:56
1

You can use time module for make a sleep time for example when pause button clicked.

code

import sys,time
from PyQt5 import QtWidgets,QtCore

class Thread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
        self.pause = False
    def run(self):
        for i in range(100):
            if self.pause:
                print("Paused")
                while self.pause:time.sleep(1)
            print("Number: "+str(i))
            time.sleep(1)
class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'QThread Pause test'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 200
        self.initUI()
    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.button = QtWidgets.QPushButton('Pause', self)
        self.button.move(175,75) 
        self.button.clicked.connect(self.thread_pause_resume)
        self.thread = Thread()
        self.show()
        self.thread.start()
    @QtCore.pyqtSlot()
    def thread_pause_resume(self):
        if self.button.text() == "Pause":
            self.thread.pause = True
            self.button.setText("Resume")
        else:
            self.thread.pause = False
            self.button.setText("Pause")

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())
Ahmed
  • 414
  • 4
  • 3