Reputation: 111
Great fellows !
I read lot of topics about this subject but I can't make it works.
This is my exemple script :
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()
When I run my Workers with run(self.done_callback)
it's working well but I loose the multi-threading effect.
And if I run it with the start(self.done_callback)
I'm facing this error message : TypeError: start() takes 1 positional argument but 2 were given
Can you explain to me what i'm doing wrong ?
Thanks in advance for your time !
Upvotes: 1
Views: 555
Reputation: 111
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()
It works !
Upvotes: 0
Reputation: 56
First, when you run your workers with new_task.start(self.done_callback)
fails because you are calling threading.Thread.start()
which only receives self
object parameter.
new_task.start()
you are passing new_task
as first argument implicitly, what's equivalent to: threadhing.Thread.start(new_task)
Also, from docs:
Once a thread object is created, its activity must be started by calling the thread’s start() method. This invokes the run() method in a separate thread of control.
So you have no control on how threading.Thread.run() is invoked, and you are overriding such method with different signature, by adding the _callback argument.
This doesn't make sense for me, since you are subclassing threading.Thread
and overriding run()
without providing its actual functionality, or splitting it in two "pieces".
In case you really need to do in that way, I would suggest not to subclass Thread and replace your Worker with something like this:
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()
You still can access threading.Thread
interface through Worker.thread
in case you need.
Upvotes: 1