如何在Python中传递和运行回调方法

nba*_*lle 24 python notifications multithreading callback

我有一个Manager(主线程),它创建其他线程来处理各种操作.我希望我的经理在创建的线程结束时(当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?
    ...
Run Code Online (Sandbox Code Playgroud)

谢谢!

kin*_*all 20

线程无法调用管理器,除非它具有对管理器的引用.最简单的方法是让管理员在实例化时将它提供给线程.

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()
Run Code Online (Sandbox Code Playgroud)

如果您希望能够将任意函数或方法指定为回调,而不是存储对管理器对象的引用,则由于方法包装器等原因,这会变得有点问题.很难设计回调,因此它获得了对管理器线程的引用,这就是你想要的.我曾经研究过一段时间,并没有想出任何我认为有用或优雅的东西.

  • 最后一行不应该是`thread.start()`吗?否则,不会发生实际的多线程,并且`MyThread.run()` 会像任何其他函数一样被执行。但是如果你真的运行了`MyThread.start()`并创建了一个新线程,`self.parent.on_thread_finished(self, 42)`仍然会在新线程的上下文而不是主线程中执行。您将需要某种同步,例如 [Queue](http://docs.python.org/library/queue.html),所以 @jonathan-lillesæter 实际上是正确的。 (2认同)
  • 我认为值得注意的是,使用此解决方案将在辅助线程而非主线程中执行回调函数。另外,在函数run中计算self.parent的用途是什么?这是为了防止如果`parent`为`None`来调用`self.parent.on_thread_finished`吗?您为什么不使用`if`语句呢?这令人困惑... (2认同)

com*_*ave 9

这样做有什么不对吗?

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"
Run Code Online (Sandbox Code Playgroud)

  • 我知道这已经很晚了,但是对于那些即将花费一个小时重写大量代码的人来说:Bharathwaaj的评论*完全不正确*并且这个答案非常有效. (9认同)