如何一次只运行一次协同程序,而不管它被调用了多少次?

2024-04-26 12:00:42 发布

您现在位置:Python中文网/ 问答频道 /正文

比如说,我有一个电子广告牌,它应该显示最新的信息,每秒可以改变不止一次。公告牌的更新程序大约需要10秒,因此每次调用并阻止它并不理想

因此,让我们将其设为一个asyncio协程,并使用asyncio.ensure_future调用它。这将使同时运行多个更新协同程序成为可能,不过,甚至可能引入竞争条件,即最后一次更新被延迟的前一次更新覆盖

有没有一个整洁的,像Python一样的方法来处理这个问题

我考虑过拥有一个内部的未来,当调用update时,它可以启动,也可以等待完成,然后再调用它。但这不会再次阻止更新吗

# create initial future and set to done
_long_update_future = asyncio.get_event_loop.create_future()
_long_update_future.set_result(0)

# takes a long time, so run asynchronously
async def long_update_function(info):
  ...

# only run the long update function one at a time
async def update(new_info):
  if not _long_update_future.done():
    # if future is already running, then wait for it first
    await _long_update_future

  _long_update_future = asyncio.ensure_future(long_update_function(new_info)


async def main():
  while True:
    new_info = block_until_new_info()

    asyncio.ensure_future(update(new_info))

Tags: runinfoasyncionewasynctimedefcreate
1条回答
网友
1楼 · 发布于 2024-04-26 12:00:42

您可以使用一个带有两个布尔标志的类来调节更新。大概是这样的:

#! python3.8

import asyncio
import random

class Updater:
    def __init__(self):
        self.in_process = False
        self.pending = False
        
    async def request(self):
        if self.in_process:
            self.pending = True
            return
        self.pending = False
        self.in_process = True
        await asyncio.sleep(2.0)  # Ten seconds is too boring
        self.in_process = False
        print("...updated")
        if self.pending:
            asyncio.create_task(self.request())
        
async def main():
    up = Updater()
    while True:
        seconds = random.random() * 4.0
        await asyncio.sleep(seconds)
        print("request")
        asyncio.create_task(up.request())
        
asyncio.run(main())
        

当第一个请求传入时,更新程序将运行。如果在处理第一个请求的过程中出现另一个请求,它将设置“挂起”标志并返回

在update函数的末尾,它检查是否有任何新的请求被挂起;如果是这样的话,它会重新安排自己。如果没有,一切都结束了。在这种情况下,在main()函数发出新请求之前,它不会再次运行

“pending”标志实际上是最大队列深度为1的请求队列。多个请求被序列化,因此一次运行的请求不超过一个。它不在乎请求到达的速度是否比处理的速度快;它处理它能处理的,并丢弃其余的

相关问题 更多 >