2012-03-21 94 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()