jerch hat geschrieben:Das geht zum Glück auch ohne Locks, da Eventsetting ja threadsafe ist.
ja das ist klar. aber ich muss (bei diesem ansatz) sicherstellen, dass beide events in einer atomaren operation gesetzt/gecleared werden. wenn das ginge würde der timer so laufen,.
jerch hat geschrieben:
Allerdings klappt das nicht mit Deinem Thread-Loop in der derzeitigen Form. Um den zu überarbeiten, müßten wir erstmal klären, was genau Du eigentlich suchst:
ich brauche den timer für einen timeout mit immer der selben länge.
ich muss den timer also starten können. dann tritt entweder der timeout auf. (der timer legt einen event in in eine queue).
oder ich stoppe den timer, falls das ereignis auf das ich warte innerhalb des timeout aufgetreten ist.
jerch hat geschrieben:
zum Code:
Dein Thread terminiert nie, da Du kein break setzt in der while True-Schleife. Wie hier vorzugehen ist, hängt von periodisch || wiederverwendbar ab bzw. solltest Du eine Abbruchvariable testen.
wenn der thread terminiert, kann ich ihn ja nicht wiederverwenden...
ich habe den code jetzt mal geändert und nutze nur noch einen event.
verstehe aber das verhalten nicht so ganz.
wenn ich den timer starte, dann direkt stoppe und dann direkt wieder starte wird nie "timer stopped" ausgegeben.
ist es nicht so, dass die methoden start_timer, stop_timer im main-thread laufen, von da aus die events setzen und im timer-thread dann nur auf die events reagiert wird?
der timer läuft also beim starten in die innere schleife und zählt die ticks.
wird jetzt der run_event gecleared, sollte die innere schleife verlassen werden und die if/else abgearbeitet werden. wird aber nicht.
(anderes problem ist, dass zu erwarten wäre, dass in meinem beispiel fälschlicherweise direkt ein fire kommt, da ich den timer ja direkt wieder aktiviere. wird in der anwendung aber so nie vorkommen. sollte aber trotzdem behoben werden.
output:
start_timer
stop_timer
TICK //warum taucht hier kein "timer stopped" auf?
start_timer
TICK
TICK
TICK
TICK
TICK
TICK
TICK
TICK
TICK
fire
Code: Alles auswählen
import threading
import time
class RU_Timer(threading.Thread):
def __init__(self, timeout, callback, *cb_args, **cb_kwargs):
self.timeout = timeout
self.callback = callback
self.cb_args = cb_args
self.cb_kwargs = cb_kwargs
self.run_event = threading.Event()
threading.Thread.__init__(self)
def stop_timer(self):
if not self.run_event.isSet():
return False
else:
self.run_event.clear()
return True
def start_timer(self):
if self.run_event.isSet():
return False
else:
self.run_event.set()
return True
def run(self):
while(True):
ticks = self.timeout
self.run_event.wait()
while(self.run_event.isSet() and ticks):
print "TICK"
ticks -= 1
time.sleep(0.1)
if self.run_event.isSet():
print "fire"
self.run_event.clear()
#self.callback(*self.cb_args, **self.cb_kwargs)
else:
print "timer stopped"
def test(a):
print a
if __name__ == "__main__":
t = RU_Timer(10, test, "timeout")
t.start()
print "start_timer"
t.start_timer()
print "stop_timer"
t.stop_timer()
print "start_timer"
t.start_timer()