单线程上有多个定时功能

时间:2018-06-22 00:10:07

标签: python multithreading python-2.7 python-multithreading

我正在阅读python threadingtimer子类上的文档,如果我想以不同的速率运行两个(或多个)定时类方法,我不太了解它的工作方式相同的线程。

例如,我有一个I / O串行设备,我想定期读取(如果有数据),从外部模块写入任何输入消息,并定期写入预定义的设备特定心跳消息。所有这些都包装在一个自定义类中。 I / O消息存储在两个单独的类队列对象中。

我需要为每个函数创建三个threading.Timer对象,还是可以以某种方式使用一个可以切换的线程?

import serial, threading, Queue
# the exact syntax below may be incorrect

class MySerialDevice:

    def __init__():
         # Some other modules will be appending to this (through a class method) 
         self.write_queue = Queue()
         self.read_queue = Queue()
         self.port = serial.Serial()
         # check for incoming data every 20ms
         self.thread1 = threading.Timer(0.02, self.read)
         # check for outgoing data every 20ms
         self.thread2 = threading.Timer(0.02, self.write)
         # Send the heaertbeat every 1 second
         self.thread3 = threading.Timer(1, self.heartbeat)

         # what do I do here???
         # can I make all three tasks on a single thread, that just continuously loops 
         # and "if incoming data, read, if outgoing data, write, heartbeat???

    def read(self):
        # checks for actual data, appending to queue are ommited
        self.port.read()
    def write(self):
        # checks for data in queue ommitted
        self.port.write(self.write_queue[0])
    def heartbeat(self):
        self.port.write("Device Heartbeat message)"

1 个答案:

答案 0 :(得分:0)

Timer很简单;没有比您看到的更多的东西了。它只运行一个计时器,一次,占用整个线程。

实际上,它作为示例代码确实比其他任何东西都多。其文档中的第二句话是“ TimerThread的子类,因此也可以作为创建自定义线程的示例。”并且threading文档链接到the source,您可以看到它很简单。


从该示例代码中构建更复杂的东西并不难。

ActiveState食谱集合中曾经有一些很好的例子。我不知道如何搜索他们的新仓库,但是您可以从a tag lookup开始。

或者,在PyPI上可以使用一堆更强大的调度程序。


或者您可以使用tick方法来重写代码。如果您每隔20毫秒进行一次滴答,则readwrite会在每个滴答滴答声中运行,而heartbeat每隔50滴答滴答地跑一次,对吧?

def __init__(self):
    self.tickcount = 0
    self.timer = threading.Timer(0.02, self.tick)

def tick(self):
    self.read()
    self.write()
    self.tickcount += 20
    if not self.tickcount % 1000:
        self.heartbeat()
    self.timer = threading.Timer(0.02, self.tick)

但是,在这一点上,编写一个每20ms循环一次的函数而不是使用计时器几乎一样简单。如果例如您需要担心不累积滞后,则扩展起来会容易得多。例如:

def ticker(self):
    last = datetime.datetime.now()
    while True:
        wake = last + datetime.timedelta(milliseconds=20)
        now = datetime.datetime.now()
        while wake > now:
            time.sleep((wake - now).total_seconds())
        self.tick()
        last = wake

现在您可以在线程中运行self.ticker


或者您可以只使用多个Timer对象。您在谈论几个对象,每个对象三个计时器,对吗?看来这不是最优雅的解决方案,但这并不会给调度程序带来负担。