How to pass and run a callback method in Python

前端 未结 3 1064
孤街浪徒
孤街浪徒 2020-12-28 14:34

I have a Manager (main thread), that creates other Threads to handle various operations. I would like my Manager to be notified when a Thread it created ends (when run() met

相关标签:
3条回答
  • 2020-12-28 14:49

    The thread can't call the manager unless it has a reference to the manager. The easiest way for that to happen is for the manager to give it to the thread at instantiation.

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

    If you want to be able to assign an arbitrary function or method as a callback, rather than storing a reference to the manager object, this becomes a bit problematic because of method wrappers and such. It's hard to design the callback so it gets a reference to both the manager and the thread, which is what you will want. I worked on that for a while and did not come up with anything I'd consider useful or elegant.

    0 讨论(0)
  • 2020-12-28 14:57

    If you want the main thread to wait for children threads to finish execution, you are probably better off using some kind of synchronization mechanism. If simply being notified when one or more threads has finished executing, a Condition is enough:

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

    However, using a Queue is probably better, as it makes handling multiple worker threads a bit easier.

    0 讨论(0)
  • 2020-12-28 15:03

    Anything wrong with doing it this way?

    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"
    
    0 讨论(0)
提交回复
热议问题