繁体   English   中英

多次调用 thread.timer()

[英]Calling thread.timer() more than once

编码:

from threading import Timer
import time

def hello():
    print "hello"

a=Timer(3,hello,())
a.start()
time.sleep(4)
a.start()

运行此脚本后,出现错误: RuntimeError: threads can only be started once因此我该如何处理此错误。 我想不止一次启动计时器。

threading.Timer继承了threading.Thread 线程对象不可重用。 您可以为每次调用创建Timer实例。

from threading import Timer
import time

class RepeatableTimer(object):
    def __init__(self, interval, function, args=[], kwargs={}):
        self._interval = interval
        self._function = function
        self._args = args
        self._kwargs = kwargs
    def start(self):
        t = Timer(self._interval, self._function, *self._args, **self._kwargs)
        t.start()

def hello():
    print "hello"

a=RepeatableTimer(3,hello,())
a.start()
time.sleep(4)
a.start()

由于我习惯在每次烤饼干时启动我的烤箱计时器,我很惊讶地看到 python 的计时器是一次性的。 也就是说,我分享了一个小的计时器类,顺便说一下,它在start方法上提供了更多选项:

  • 返回自身以允许创建和启动单行计时器
  • 可选参数是否重新启动新计时器,如果计时器仍然存在

执行:

from threading import Timer, Lock


class TimerEx(object):
    """
    A reusable thread safe timer implementation
    """

def __init__(self, interval_sec, function, *args, **kwargs):
    """
    Create a timer object which can be restarted

    :param interval_sec: The timer interval in seconds
    :param function: The user function timer should call once elapsed
    :param args: The user function arguments array (optional)
    :param kwargs: The user function named arguments (optional)
    """
    self._interval_sec = interval_sec
    self._function = function
    self._args = args
    self._kwargs = kwargs
    # Locking is needed since the '_timer' object might be replaced in a different thread
    self._timer_lock = Lock()
    self._timer = None

def start(self, restart_if_alive=True):
    """
    Starts the timer and returns this object [e.g. my_timer = TimerEx(10, my_func).start()]

    :param restart_if_alive: 'True' to start a new timer if current one is still alive
    :return: This timer object (i.e. self)
    """
    with self._timer_lock:
        # Current timer still running
        if self._timer is not None:
            if not restart_if_alive:
                # Keep the current timer
                return self
            # Cancel the current timer
            self._timer.cancel()
        # Create new timer
        self._timer = Timer(self._interval_sec, self.__internal_call)
        self._timer.start()
    # Return this object to allow single line timer start
    return self

def cancel(self):
    """
    Cancels the current timer if alive
    """
    with self._timer_lock:
        if self._timer is not None:
            self._timer.cancel()
            self._timer = None

def is_alive(self):
    """
    :return: True if current timer is alive (i.e not elapsed yet)
    """
    with self._timer_lock:
        if self._timer is not None:
            return self._timer.is_alive()
    return False

def __internal_call(self):
    # Release timer object
    with self._timer_lock:
        self._timer = None
    # Call the user defined function
    self._function(*self._args, **self._kwargs)

这里有一个例子:

from time import sleep

def my_func(msg):
    print(msg)

my_timer = TimerEx(interval_sec=5, function=my_func, msg="Here is my message").start()
sleep(10)
my_timer.start()
sleep(10)

注意:我使用的是 python 3.7,所以我不能 100% 确定这适用于 Python 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM