Как передать и запустить метод обратного вызова в Python
У меня есть менеджер (основной поток), который создает другие потоки для обработки различных операций.
Я хочу, чтобы мой Менеджер был уведомлен о завершении Созданного потока (при выполнении метода run()).
Я знаю, что могу сделать это, проверив статус всех моих потоков с помощью метода Thread.isActive(), но опрос сосет, поэтому я хотел получить уведомления.
Я думал дать метод обратного вызова Threads и вызвать эту функцию в конце метода 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?
...
Спасибо!
Ответы
Ответ 1
Нить не может вызвать менеджера, если у него нет ссылки на менеджера. Самый простой способ для этого - менеджеру передать его в поток при создании экземпляра.
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()
Если вы хотите иметь возможность назначать произвольную функцию или метод в качестве обратного вызова, а не хранить ссылку на объект-менеджер, это становится немного проблематичным из-за оберток методов и т.д. Трудно спроектировать обратный вызов, поэтому он получает ссылку как на менеджера, так и на поток, и это то, что вам нужно. Я работал над этим некоторое время и не придумал ничего, что считал бы полезным или элегантным.
Ответ 2
Что-то не так с этим?
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"
Ответ 3
Если вы хотите, чтобы основной поток дождался, когда дочерние потоки закончат выполнение, вам, вероятно, лучше использовать какой-то механизм синхронизации. Если просто получать уведомления о завершении выполнения одного или нескольких потоков, достаточно Condition:
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()
Однако использование Queue, вероятно, лучше, так как упрощает обработку нескольких рабочих потоков.