I am trying to make a program loop with a timer that runs separately which for every iteration, the code continues where the timer countdown is left.
I drawed this pseudo code. It is the main idea on what i am trying to achieve (please play close attention). Basically while the timer is going, i want the next iteration to jump to where the timer currently is.
I tried writing a code, of course its wrong
import time
import threading
def scan_if_won():
#returns True or False
def wait_for_start_signal():
#returns True or False
def main():
print("Action 0")
while True:
time.sleep(20) #or any other timer function
while wait_for_start_signal() == False: #usually takes 6-9 seconds, we never know exact time
start = wait_for_start_signal()
if start == True:
break
#reset timer, countdown from 20
time.sleep(3)
result = scan_if_won() #this scan is not instant, can take from 1 to 2 seconds
if result == False
print("Action 1")
if result == True
print("Action 2")
#Now somehow, at next iteration, time.sleep() value should be the 20 - 3 - scan_if_won() time
main()
Was thinking of implementing threading but i have no idea how to start the thread from inside loop, kill it (if needed) and share variables (timer current value) between threads while being in a loop.
Please look at my pseudo code again for fully understanding my issue.
Thanks
Edit:
here is the output of the code:
https://dpaste.org/6NpHu
why does the win/lose Actions happen twice at the same time? looks like a tread should be stopped
I think below code solve the problem if no bug. Event() class is very usefull for this kind of problems. I modified a little your code.
import time
import threading
def scan_if_won():
time.sleep(2)
return False
def wait_for_start_signal():
time.sleep(7)
return True
def check_start_signal(time):
event2.wait(timeout=time)
event2.clear()
while 1:
start=wait_for_start_signal()
if start:
event.set()
return
def main():
print("Action 0")
while True:
try:
t # is thread (t) created ?
event.wait()
event.clear()
except UnboundLocalError:
check_start_signal(20)
t=threading.Thread(target=check_start_signal,args=(20,))
t.start()
time.sleep(3)
result = scan_if_won() #this scan is not instant, can take from 1 to 2 seconds
if result == False:
print("Action 1")
if result == True:
print("Action 2")
#Now somehow, at next iteration, time.sleep() value should be the 20 - 3 - scan_if_won() time
event=threading.Event()
event2=threading.Event()
main()
Edit :
In above code, check_start_signal()
will be called by main thread and also event.set()
will be called before the event.wait()
called. After check_start_signal()
completed, new thread will be created and in second iteration, event.wait()
will be checked in try block, but event.wait()
will not block the main thread because we set the internal flag to True of event object in first check_start_signal()
func by event.set()
. That's why you have more threads and your code messed
I modified the check_start_signal()
function as following:
def check_start_signal(time):
event2.wait(time)
event2.clear
print("passed 20 sec")
while 1:
start=wait_for_start_signal()
print(start)
if start:
if threading.current_thread().__class__.__name__ != '_MainThread':
event1.set()
return
Note: In comments, i said "I measured "Action 1" message period that is 20 seconds" actually it was true in my first answer, you can look at my first answer in revisions, it contains "time.sleep(20-passed)" function end of the while loop, that's why i measured the 20 seconds. My first answer was not good and there were some bugs where i mentioned above