Reputation: 974
I have a thread, where I am using an thread event to control the thread from outside the target function.
flag = threading.event()
In my target function, I have something like this:
def functionname(arguments):
flag.clear()
while not flag.wait(timeout = 0.5):
# do something.
whenever I want to return the thread, from my main function I say, flag.set(). Then flag is set to true, my target function completes execution and the thread is completed.
Now, if I want to use flag.wait(timeout = 5) in my main function, I am expecting to block and wait for five seconds to execute the "do something" part of code. However I am seeing that the "do something" part of the code is executing every 0.5 seconds as usual and my main function is blocked for five seconds.
The wait method has to block until the flag is true or the optional time out ends. It is blocking my main function rather than the target function. Can any one know why this might be?
PS: I defined the flag event in my main function and passed it as an argument to the target function
Upvotes: 1
Views: 3581
Reputation: 77347
Many threads can wait on an event at the same time and how long one waits before timeout is independent of how long the others do. If you want your thread's wait time to change from .5 to 5 seconds, then you need some way to tell the thread to change the value it passes in the timeout parameter. This seems like a good job for a shared variable - the thread reads timeout from the variable and main can change that variable.
But where do you put it? Well, class instances exist to hold associated data so a class holding the event and the current timeout value is reasonable. In fact, you can just use inheritance to do the job. Notice in this example, the timeout is only changed for the next interval - the thread waits the current wait time before using the updated value. Getting the change immediately is significantly more difficult and I didn't want to confuse the matter.
import threading
import time
class VariablyTimedEvent(threading.Event):
def __init__(self, initial_timeout=None):
super().__init__()
self.timeout = initial_timeout
def wait(self):
return super().wait(timeout=self.timeout)
# ------------- test -----------------
def functionname(event):
event.clear()
while not event.wait():
do_something()
print('event set, exiting')
_do_something_start = time.time()
def do_something():
# a mock object that shows time since program start
print('%03.1f: do something' % (time.time() - _do_something_start))
print("start timing at .5 second")
event = VariablyTimedEvent(.5)
thread = threading.Thread(target=functionname, args=(event,))
thread.start()
time.sleep(3.1)
print("change timeout to 2 seconds")
event.timeout = 2
time.sleep(7)
print("exit the thread")
event.set()
thread.join()
Upvotes: 2