43

我正在尝试编写一个倒计时到给定时间的方法,除非给出重新启动命令,否则它将执行任务。但我认为 Pythonthreading.Timer类不允许取消计时器。

import threading

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

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

    t.start()

我知道上面的代码在某种程度上是错误的。希望能在这里得到一些善意的指导。

4

5 回答 5

39

启动计时器后,您将调用取消方法:

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()
于 2012-03-21T21:02:04.700 回答
16

我不确定我是否理解正确。你想写类似这个例子的东西吗?

>>> 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()
>>>
于 2012-03-21T21:01:43.997 回答
8

该类threading.Timer确实有一个方法,虽然它不会取消线程但它会阻止计时器实际触发。实际发生的是该方法设置了 a ,并且实际执行的线程将在等待完成后和实际执行回调之前检查该事件。cancelcancelthreading.Eventthreading.Timer

也就是说,定时器通常是在不为每个定时器使用单独线程的情况下实现的。最好的方法取决于你的程序实际在做什么(在等待这个计时器时),但是任何带有事件循环的东西,比如 GUI 和网络框架,都有办法请求一个连接到事件循环中的计时器。

于 2012-03-21T21:02:26.070 回答
1

我不确定最好的选择,但对我来说是这样的:t = timer_mgr(.....)附加到列表“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()
于 2021-05-07T07:01:08.980 回答
0

灵感来自上面的帖子。Python 中的可取消和重置计时器。它使用线程。
特点:启动、停止、重启、回调函数。
输入:超时、sleep_chunk 值和回调函数。
可以在任何其他程序中使用或继承此类。也可以将参数传递给回调函数。
定时器也应该在中间响应。不仅仅是在完成完整的睡眠时间之后。因此,不要使用完全睡眠,而是使用小块睡眠并不断检查事件对象循环。

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()
于 2017-04-03T15:55:23.830 回答