Bonjour à tous
Comme beaucoup ici, je me suis intéressé aux QThreads afin de pouvoir déporter certains traitements longs. Mais comme pour tout, il m'a fallu apprendre. Et dans cette phase d'apprentissage, après différents essais, j'arrive sur un blocage avec la fonction "moveToObject()" que je n'arrive pas à faire fonctionner...
Tout d'abord, pour vérifier la faisabilité du thread, j'écris mon premier thread, largement inspiré de ce tutoriel.
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
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 #!/usr/bin/env python # -*- coding: utf-8 -*- from PyQt4.QtGui import * from PyQt4.QtCore import * import sys class MyThread(QThread): def __init__(self, limit, prior, name=None, *args, **kwargs): QThread.__init__(self, *args, **kwargs) self.__prior=prior self.__name=name self.__limit=limit # __init__() def run(self): self.setPriority(self.__prior) for i in xrange(self.__limit): qDebug("nom: %s (%x), i=%d" % (self.__name, self.currentThreadId(), i)) # run() # class MyThread if __name__ == "__main__": app=QCoreApplication (sys.argv) qDebug("app: %x" % app.thread().currentThreadId()) thread=[ MyThread(5, prior, name)\ for (name, prior) in ( ("A", QThread.IdlePriority), ("B", QThread.NormalPriority), ("C", QThread.TimeCriticalPriority), ) ] for t in thread: t.start() QTimer.singleShot(2000, app, SLOT("quit()")) app.exec_() for t in thread: t.quit() # if
A l'exécution, tout va bien. J'ai bien mes "A", "B" et "C" avec des currentThreadId() tous différents (et différents de celui du QApplication) et je vois que le thread C (le plus prioritaire) se déroule le premier.
Ensuite, je m'intéresse à la possibilité d'intégrer un QObject. Je trouve à ce propos ce très bel article vous vous y prenez mal que je lis avec attention et où je suis attiré par cette phrase
.Télécharger un fichier, interroger une base de données ou faire tout autre type de traitements ne devrait pas être ajouté dans une sous-classe de QThread. Il devrait être encapsulé dans un objet qui lui est propre... Pour exécuter votre code dans un nouveau thread, vous devriez instancier un QThread et assigner votre objet à ce thread en utilisant la fonction moveToThread()
J'en conclus qu'il faut créer un QObjet indépendant qui fait le travail, puis envoyer l'objet dans le thread avec moveToObject() pour que ce travail soit fait par le thread.
Malheureusement, rien de ce que je fais ne fonctionne. En désespoir de cause, je vais jusqu'à aller regarder le code source de l'exemple movedobject qu'on peut trouver dans les exemples du source de la librairie Qt. Je prends ce source et en crée une adaptation Python. Ce qui donne le code suivant
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
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 #!/usr/bin/env python # -*- coding: utf-8 -*- from PyQt4.QtGui import * from PyQt4.QtCore import * import sys class WorkerObject(QObject): def __init__(self, ms, parent=None, *args, **kwargs): QObject.__init__(self, parent, *args, **kwargs) self.__timer=QTimer() self.connect(self.__timer, SIGNAL("timeout()"), self.__poll) self.__count=0 self.__ms=ms # __init__() def startPolling(self): qDebug("start polling in thread %x" % self.thread().currentThreadId()) self.__count=0 self.__timer.start(self.__ms) # startPolling() def stopPolling(self, ms): self.__timer.stop() # stopPolling() def __poll(self): qDebug("timer hit %d (%x)" % (self.__count, self.thread().currentThreadId())) self.__count+=1 # __poll() # class WorkerObject class Thread(QThread): def __init__(self, parent=None, *args, **kwargs): QThread.__init__(self, parent, *args, **kwargs) # __init__() def launchWorker(self, worker): qDebug("%x launchWorker()" % self.currentThreadId()) worker.moveToThread(self) self.start() # launcherWorkerObject() def stopExecutor(self): qDebug("%x stopExecutor()" % self.currentThreadId()) self.quit() # stopExecutor() # class Thread if __name__ == "__main__": app=QCoreApplication(sys.argv) qDebug("mainThread=%x" % app.thread().currentThreadId()) thread=Thread() worker=WorkerObject(500) QObject.connect( thread, SIGNAL("started()"), worker.startPolling, ) QObject.connect( thread, SIGNAL("finished()"), worker.stopPolling, ) thread.launchWorker(worker) QTimer.singleShot(3000, app, SLOT("quit()")) app.exec_() thread.stopExecutor() # if
cette adaptation, bien qu'épurée de certains détails présents dans l'exemple C++, me semble quand-même fonctionnelle pour mes tests. Or quand j'exécute ce code, les valeurs affichées aux différents "currentThreadId()" sont pourtant toutes identiques à celles du QApplication
Arrivé là, je ne vois pas quoi faire de plus pour réussir à déporter mon objet dans son thread...
Merci de votre attention
Partager