J'ai un gestionnaire (thread principal), qui crée d'autres threads pour gérer diverses opérations. Je voudrais que mon gestionnaire soit averti lorsqu'un thread qu'il a créé se termine (lorsque l'exécution de la méthode run () est terminée).
Je sais que je pourrais le faire en vérifiant l'état de tous mes threads avec la méthode Thread.isActive (), mais l'interrogation craint, donc je voulais avoir des notifications.
Je pensais donner une méthode de rappel aux Threads, et appeler cette fonction à la fin de la méthode run ():
class Manager():
...
MyThread(self.on_thread_finished).start() # How do I pass the callback
def on_thread_finished(self, data):
pass
...
class MyThread(Thread):
...
def run(self):
....
self.callback(data) # How do I call the callback?
...
Merci!
Le thread ne peut pas appeler le gestionnaire à moins qu'il ait une référence au gestionnaire. Le moyen le plus simple pour que cela se produise est que le gestionnaire le donne au thread lors de l'instanciation.
class Manager(object):
def new_thread(self):
return MyThread(parent=self)
def on_thread_finished(self, thread, data):
print thread, data
class MyThread(Thread):
def __init__(self, parent=None):
self.parent = parent
super(MyThread, self).__init__()
def run(self):
# ...
self.parent and self.parent.on_thread_finished(self, 42)
mgr = Manager()
thread = mgr.new_thread()
thread.start()
Si vous souhaitez pouvoir affecter une fonction ou une méthode arbitraire en tant que rappel, plutôt que de stocker une référence à l'objet gestionnaire, cela devient un peu problématique en raison des wrappers de méthode et autres. Il est difficile de concevoir le rappel, il obtient donc une référence à la fois au gestionnaire et au thread, ce que vous voudrez. J'ai travaillé là-dessus pendant un certain temps et je n'ai rien trouvé de utile ou d'élégant.
Quelque chose de mal à le faire de cette façon?
from threading import Thread
class Manager():
def Test(self):
MyThread(self.on_thread_finished).start()
def on_thread_finished(self, data):
print "on_thread_finished:", data
class MyThread(Thread):
def __init__(self, callback):
Thread.__init__(self)
self.callback = callback
def run(self):
data = "hello"
self.callback(data)
m = Manager()
m.Test() # prints "on_thread_finished: hello"
Si vous voulez que le thread principal attende que les threads enfants terminent l'exécution, il est probablement préférable d'utiliser une sorte de mécanisme de synchronisation. Si simplement être averti quand un ou plusieurs threads ont fini de s'exécuter, une Condition suffit:
import threading
class MyThread(threading.Thread):
def __init__(self, condition):
threading.Thread.__init__(self)
self.condition = condition
def run(self):
print "%s done" % threading.current_thread()
with self.condition:
self.condition.notify()
condition = threading.Condition()
condition.acquire()
thread = MyThread(condition)
thread.start()
condition.wait()
Cependant, l'utilisation de Queue est probablement meilleure, car elle facilite un peu la gestion de plusieurs threads de travail.