2012-03-21 102 views
23

我正在嘗試編寫一種方法,它可以倒計時到給定時間,除非給出重新啓動命令,否則它將執行任務。但我不認爲類Python允許定時器被取消。Python中可取消線程。定時器

import threading 

def countdown(action): 
    def printText(): 
     print 'hello!' 

    t = threading.Timer(5.0, printText) 
    if (action == 'reset'): 
     t.cancel() 

    t.start() 

我知道上面的代碼在某種程度上是錯誤的。希望能在這裏得到一些指導。

回答

12

我不確定我是否理解正確。你想寫這樣的例子嗎?

>>> 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() 
>>> 
+0

這是最好的。如果你的程序沒有立即終止,那麼這將是*好的*,只有一個「你好」並且沒有任何延遲! :)你必須根據某些條件將't.cancel()'合併到'sayHello()'函數中。 'if counter == 10:t.cancel()'。那會有意義的。 – Apostolos 2018-03-01 22:45:21

+0

對不起。即使那樣也不會很好。如果在調用'sayHello(0)'後添加任何代碼,它將在定時器測試結束前執行! (自己動手,在代碼末尾添加例如'print'Done'')。 – Apostolos 2018-03-01 23:12:36

25

你會打電話取消方法啓動定時器後:

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循環,而不是使用定時器
這裏是尼古拉斯·Gradwohl的answer撥到另一個問題的例子:

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() 
+0

請解釋爲什麼你認爲定時while循環比thread定時器更好。 – 2017-01-30 05:32:18

+1

@WesModes我提供了一個可以打印倒計數的替代方案。 – 2017-01-31 01:35:22

+0

適合我。雖然我使用的時候不是self.event.wait(1)每秒執行一次,而不是count變量 – mtosch 2017-09-23 11:53:27

6

threading.Timercancel方法,雖然它不會取消線程,它會停止計時器從實際開火。實際上發生的是cancel方法設置了threading.Event,並且實際執行threading.Timer的線程將在完成等待並且實際執行回調之前檢查該事件。

也就是說,定時器通常使用而不是使用每個單獨的線程。最好的方法取決於你的程序實際在做什麼(在等待這個定時器的時候),但是任何帶有事件循環的東西,比如GUI和網絡框架,都有辦法請求一個掛在事件回調中的定時器。

0

受上述帖子的啓發。 在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()