How to make program that runs a timer and the code separately but interacts with it?

Question:

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.
enter image description here

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

Asked By: George Rabus

||

Answers:

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

Answered By: Veysel Olgun
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.