【问题标题】:Python - Callback from method to another classPython - 从方法回调到另一个类
【发布时间】:2020-06-12 09:31:05
【问题描述】:

好家伙!

我阅读了很多关于这个主题的主题,但我无法让它发挥作用。

这是我的示例脚本:

import time, threading, collections


class Factory () :

    def __init__(self):
        self.to_do_list = collections.deque()

    def run(self):
        while self.to_do_list :
            new_task = self.to_do_list.popleft()
            new_task.start(self.done_callback)

    def add_worker(self, task):
        self.to_do_list.append(task)

    def done_callback(self):
            print("OK - DONE")

class Worker (threading.Thread):

    def __init__(self, _name):
        threading.Thread.__init__(self)
        self.name = _name

    def run(self, _callback):
        self.callback = _callback
        for i in range (0,5):
            print(self.name+" -- "+str(i))
            time.sleep(0.5)     
        self.callback()

worker_1 = Worker("Anakin")
worker_2 = Worker("Obi-Wan")
worker_3 = Worker("Yoda")

factory = Factory()

factory.add_worker(worker_1)
factory.add_worker(worker_2)
factory.add_worker(worker_3)

factory.run()

当我使用 run(self.done_callback) 运行我的 Workers 时,它运行良好,但我失去了多线程效果。

如果我使用 start(self.done_callback) 运行它,我将面临以下错误消息:TypeError: start() takes 1 positional argument but 2 were given

你能解释一下我做错了什么吗?

提前感谢您的宝贵时间!

【问题讨论】:

    标签: python multithreading class object


    【解决方案1】:

    首先,当您使用 new_task.start(self.done_callback) 运行工作人员时失败,因为您正在调用仅接收 self 对象参数的 threading.Thread.start()

    • 请注意,当您调用new_task.start() 时,您将new_task 作为第一个参数隐式传递,相当于:threadhing.Thread.start(new_task)

    另外,来自docs

    一旦创建了线程对象,它的活动必须通过调用线程的 start() 方法来启动。这会在单独的控制线程中调用 run() 方法。

    因此,您无法控制 threading.Thread.run() 的调用方式,并且通过添加 _callback 参数来覆盖具有不同签名的此类方法。

    这对我来说没有意义,因为您将 threading.Thread 子类化并覆盖 run() 而不提供其实际功能,或者将其拆分为两个“部分”。

    如果你真的需要这样做,我建议不要子类化 Thread 并用这样的东西替换你的 Worker:

    class Worker:
    
    def __init__(self, _name):
        self.thread = None
        self.name = _name
    
    def run(self, _callback):
        self.thread = threading.Thread(target=self._p_run, args=(_callback,))
        self.thread.start()
    
    def _p_run(self, _callback):
        for i in range(0, 5):
            print(self.name+" -- "+str(i))
            time.sleep(0.5)
        _callback()
    

    如果需要,您仍然可以通过Worker.thread访问threading.Thread接口。

    【讨论】:

    • 感谢您的准确解释。因此,通过 start() 方法传递参数并不是一个好主意,因为它是由threading.Thread 处理的。我试过这种方式:new_task = self.to_do_list.popleft(); new_task.callback = self.done_callback; new_task.start();(我用整个代码编辑了我的答案)我对这个实现更满意。这是一个好方法吗?
    • 根本不认为这是一个好方法。在您的代码中,Worker.callback 方法是在Factory 动态创建的,但仍会在Worked.run 内调用。这意味着您的threadhing.Thread 子类Worker 在被Factory 处理之前完全被破坏,因此您将实现一段不起作用的代码。即使添加了抽象方法Workder.callback,在封装性、可读性和耦合性方面仍然不是一个好主意。
    【解决方案2】:

    V2:

    import time, threading, collections
    
    class Factory () :
    
        def __init__(self):
            self.to_do_list = collections.deque()
    
        def run(self):
            while self.to_do_list :
                new_task = self.to_do_list.popleft()
                new_task.callback = self.done_callback
                new_task.start()
    
        def add_worker(self, task):
            self.to_do_list.append(task)
    
        def done_callback(self):
                print("OK - DONE")
    
    class Worker (threading.Thread):
    
        def __init__(self, _name):
            threading.Thread.__init__(self)
            self.name = _name
    
        def run(self):
    
            for i in range (0,5):
                print(self.name+" -- "+str(i))
                time.sleep(0.5)     
            self.callback()
    
    factory = Factory()
    
    worker_1 = Worker("Tomtom")
    worker_2 = Worker("Nana")
    worker_3 = Worker("Pikachu")
    
    factory.add_worker(worker_1)
    factory.add_worker(worker_2)
    factory.add_worker(worker_3)
    
    factory.run()
    
    

    有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-07
      相关资源
      最近更新 更多