Utiliser correctement les threads
Bonjour a tous,
Je suis en train de faire une application qui a pour role de scanner des dossiers sur un réseau
en continu afin de produire un rapport dans une base de donnee, accessible via une interface en Qt.
Je suis donc obligé de créer une application qui a deux threads :
Le premier thread est celui de l'application principale, qui affichera le contenu de la BDD.
Et un second thread qui est le "scanner de dossiers".
Pour bien reussir cette application, j'ai décidé de commencer par un genre de test.
Ce test est un compteur avec 3 boutons : Start, Stop et Reset.
J'ai parcouru de nombreux forums, j'ai lu tout un tas d'article et de docs, mais je dois avouer que je ne me sent pas encore a l'aise avec le concept.
Pour l'instant je n'arrive pas à arrêter mon compteur une fois qu'il est démarré.
Le thread se termine sans répondre.
Voici le code du programme, j'espère que vous pourrez m'aider !
Vous pouvez l'executer directement, vous comprendrez tout de suite le problème : Si on appuie sur start, plus rien ne répond...
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| from PyQt4 import QtCore, QtGui
import time
class counter(QtCore.QObject) :
# le compteur
def __init__(self) :
super(counter,self).__init__()
self.sh = None
self.stop = False
self.count = 0
self.maxCount = 50
def setSH(self,sh) :
self.sh = sh
def startCount(self) :
self.sh.textSignal.emit( "Starting..." )
self.stop = False
while not self.stop :
self.sh.textSignal.emit( str( self.count ) )
self.count = self.count + 1
time.sleep(0.1)
if self.count > self.maxCount :
self.stop = True
self.sh.textSignal.emit( "Finished..." )
def stopCount(self) :
self.sh.textSignal.emit( "Stopping..." )
self.stop = True
def resetCount(self) :
self.sh.textSignal.emit( "Reseting..." )
self.count = 0
def quit(self) :
self.stop = True
self.parent.quit()
class signalsHolder(QtCore.QObject) :
# un conteneur pour mes signaux
startSignal = QtCore.pyqtSignal()
stopSignal = QtCore.pyqtSignal()
resetSignal = QtCore.pyqtSignal()
killThreadSignal = QtCore.pyqtSignal()
textSignal = QtCore.pyqtSignal(str)
class cpt(QtGui.QMainWindow):
#l'application principale, avec l'interface et les boutons et un log
def __init__(self):
super(cpt, self).__init__()
self.sh = None
self.log = QtGui.QPlainTextEdit()
self.log.setPlainText( "Welcome ! " )
startScanButton = QtGui.QPushButton("Start")
startScanButton.clicked.connect( self.startThread )
stopScanButton = QtGui.QPushButton("Stop")
stopScanButton.clicked.connect( self.stopThread )
resetScanButton = QtGui.QPushButton("Reset")
resetScanButton.clicked.connect( self.resetThread )
buttonsBarlayout = QtGui.QHBoxLayout()
buttonsBarlayout.addWidget( startScanButton )
buttonsBarlayout.addWidget( stopScanButton )
buttonsBarlayout.addWidget( resetScanButton )
self.buttonsBar = QtGui.QGroupBox("Actions : ")
self.buttonsBar.setLayout(buttonsBarlayout)
self.mainLayout = QtGui.QGridLayout()
self.mainLayout.addWidget( self.buttonsBar , 0,0)
self.mainLayout.addWidget( self.log , 1,0)
mainWidget = QtGui.QWidget()
mainWidget.setLayout(self.mainLayout)
self.setCentralWidget(mainWidget)
def setSH(self,sh) :
self.sh = sh
def atl(self,infos) :
# Ajoute des infos dans le log
self.log.appendPlainText(infos)
def startThread(self) :
self.sh.startSignal.emit()
def stopThread(self) :
self.sh.stopSignal.emit()
def resetThread(self) :
self.sh.resetSignal.emit()
def quit(self) :
self.sh.killThreadSignal.emit()
def main() :
import sys
app = QtGui.QApplication(sys.argv)
mainWindow = cpt()
sh = signalsHolder()
mainWindow.setSH(sh)
thisCounter = counter()
thisCounter.setSH(sh)
sh.startSignal.connect(thisCounter.startCount)
sh.stopSignal.connect(thisCounter.stopCount)
sh.resetSignal.connect(thisCounter.resetCount)
sh.textSignal.connect(mainWindow.atl)
thisThread = QtCore.QThread(None)
sh.killThreadSignal.connect(thisCounter.quit)
thisCounter.moveToThread(thisThread)
thisThread.start()
mainWindow.show()
sys.exit( app.exec_() )
if __name__ == '__main__':
main() |