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

28 投票
3 回答
58531 浏览
提问于 2025-04-16 22:08

我有一个管理者(主线程),它会创建其他线程来处理各种操作。
我希望当它创建的线程结束时(也就是run()方法执行完毕时),能通知我的管理者。

我知道可以通过检查所有线程的状态来实现,使用Thread.isActive()这个方法,但这样一直去检查状态很麻烦,所以我想要有通知功能。

我在想给线程提供一个回调方法,然后在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?
    ...

谢谢!

3 个回答

4

如果你想让主线程等子线程执行完毕,使用某种同步机制会更好。比如,如果你只是想在一个或多个线程执行完后收到通知,使用一个条件对象就可以了:

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()

不过,使用队列可能会更好,因为这样处理多个工作线程会简单一些。

10

这样做有什么问题吗?

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"
25

线程不能调用管理者,除非它有管理者的引用。最简单的办法就是在创建线程的时候,管理者把它的引用给线程。

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()

如果你想要能够随意指定一个函数或方法作为回调,而不是直接存储管理者对象的引用,这就有点麻烦了,因为涉及到方法的包装等问题。设计回调函数时,要让它同时获取管理者和线程的引用,这样会比较复杂。我尝试了很久,但没找到什么我觉得有用或优雅的解决方案。

撰写回答