[英]Cancellable threading.Timer in Python
我正在嘗試編寫一個倒計時到給定時間的方法,除非給出重新啟動命令,否則它將執行任務。 但我不認為 Python threading.Timer
類允許計時器被取消。
import threading
def countdown(action):
def printText():
print 'hello!'
t = threading.Timer(5.0, printText)
if (action == 'reset'):
t.cancel()
t.start()
我知道上面的代碼不知何故是錯誤的。 很感激這里的一些指導。
您將在啟動計時器后調用取消方法:
import time
import threading
def hello():
print "hello, world"
time.sleep(2)
t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
t.cancel()
您可能會考慮在Thread上使用 while 循環,而不是使用Timer 。
以下是 Nikolaus Gradwohl 對另一個問題的回答中的一個示例:
import threading
import time
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.count = 10
def run(self):
while self.count > 0 and not self.event.is_set():
print self.count
self.count -= 1
self.event.wait(1)
def stop(self):
self.event.set()
tmr = TimerClass()
tmr.start()
time.sleep(3)
tmr.stop()
我不確定我是否理解正確。 你想在這個例子中寫一些類似的東西嗎?
>>> import threading
>>> t = None
>>>
>>> def sayHello():
... global t
... print "Hello!"
... t = threading.Timer(0.5, sayHello)
... t.start()
...
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>
threading.Timer
類確實有一個cancel
方法,雖然它不會取消線程,但它會阻止計時器實際觸發。 實際發生的是cancel
方法設置了一個threading.Event
,而實際執行threading.Timer
將在完成等待之后和實際執行回調之前檢查該事件。
也就是說,定時器的實現通常不會為每個定時器使用單獨的線程。 最好的方法取決於你的程序實際在做什么(在等待這個計時器時),但是任何帶有事件循環的東西,比如 GUI 和網絡框架,都有方法來請求一個掛接到事件循環中的計時器。
我不確定是否最好的選擇,但對我來說是這樣的: t = timer_mgr(.....) append to list "timers.append(t)" 然后在創建之后你可以調用:
for tm in timers:#threading.enumerate():
print "********", tm.cancel()
我的 timer_mgr() 類是這樣的:
class timer_mgr():
def __init__(self, st, t, hFunction, id, name):
self.is_list = (type(st) is list)
self.st = st
self.t = t
self.id = id
self.hFunction = hFunction
self.thread = threading.Timer(t, self.handle_function, [id])
self.thread.name = name
def handle_function(self, id):
if self.is_list:
print "run_at_time:", datetime.now()
self.hFunction(id)
dt = schedule_fixed_times(datetime.now(), self.st)
print "next:", dt
self.t = (dt-datetime.now()).total_seconds()
else:
self.t = self.st
print "run_every", self.t, datetime.now()
self.hFunction(id)
self.thread = threading.Timer(self.t, self.handle_function, [id])
self.thread.start()
def start(self):
self.thread.start()
def cancel(self):
self.thread.cancel()
靈感來自上面的帖子。 Python 中的可取消和重置計時器。 它使用線程。
功能:啟動、停止、重啟、回調函數。
輸入:超時、sleep_chunk 值和 callback_function。
可以在任何其他程序中使用或繼承此類。 也可以將參數傳遞給回調函數。
定時器也應該在中間響應。 不僅僅是在完成完整的睡眠時間之后。 因此,與其使用一個完整的睡眠,不如使用一小塊睡眠並在循環中不斷檢查事件對象。
import threading
import time
class TimerThread(threading.Thread):
def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
threading.Thread.__init__(self)
self.timeout = timeout
self.sleep_chunk = sleep_chunk
if callback == None:
self.callback = None
else:
self.callback = callback
self.callback_args = args
self.terminate_event = threading.Event()
self.start_event = threading.Event()
self.reset_event = threading.Event()
self.count = self.timeout/self.sleep_chunk
def run(self):
while not self.terminate_event.is_set():
while self.count > 0 and self.start_event.is_set():
# print self.count
# time.sleep(self.sleep_chunk)
# if self.reset_event.is_set():
if self.reset_event.wait(self.sleep_chunk): # wait for a small chunk of timeout
self.reset_event.clear()
self.count = self.timeout/self.sleep_chunk # reset
self.count -= 1
if self.count <= 0:
self.start_event.clear()
#print 'timeout. calling function...'
self.callback(*self.callback_args)
self.count = self.timeout/self.sleep_chunk #reset
def start_timer(self):
self.start_event.set()
def stop_timer(self):
self.start_event.clear()
self.count = self.timeout / self.sleep_chunk # reset
def restart_timer(self):
# reset only if timer is running. otherwise start timer afresh
if self.start_event.is_set():
self.reset_event.set()
else:
self.start_event.set()
def terminate(self):
self.terminate_event.set()
#=================================================================
def my_callback_function():
print 'timeout, do this...'
timeout = 6 # sec
sleep_chunk = .25 # sec
tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
tmr.start()
quit = '0'
while True:
quit = raw_input("Proceed or quit: ")
if quit == 'q':
tmr.terminate()
tmr.join()
break
tmr.start_timer()
if raw_input("Stop ? : ") == 's':
tmr.stop_timer()
if raw_input("Restart ? : ") == 'r':
tmr.restart_timer()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.