单个线程上的多个定时函数



我正在阅读有关pythonthreadingtimer子类的文档,如果我想在同一线程上以不同的速率运行两个(或更多(定时类方法,我不太明白它会如何工作。

例如,我有一个 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)"

Timer非常简单;没有什么比你看到的更多了。它运行一个计时器,一次,占用整个线程来执行此操作。

事实上,它实际上更多的是作为示例代码而不是其他任何东西。其文档中的第二句话是"TimerThread的子类,因此也可以用作创建自定义线程的示例。threading文档链接到源代码,您可以看到它是多么简单。


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

ActiveState 配方集合中曾经有一些很好的例子。我不知道如何搜索他们的新存储库,但您可以从标签查找开始。

或者,有一堆更强大的调度程序可以在 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)

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

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对象。你说的是几个对象和每个对象三个计时器,对吧?这似乎不是最优雅的解决方案,但它不会使调度程序负担过重。

最新更新