等待为 asyncio.Event 设置超时或事件

Wait for timeout or event being set for asyncio.Event

我有一个 class,其方法如下所示:

# self.stop_event -> threading.Event
def run(self):
    while not self.stop_event.wait(3):  # i.e. repeat every 3 sec
        pass  # do stuff

想法是,其中几个 运行 在它们自己的线程中,有时一个线程 stop_event.set(),这自然会停止所有其他线程。我想为此切换到 asyncio,因为 run 中的任务主要是在睡觉和做 IO。因此,我必须:

# self.stop_event -> asyncio.Event
async def run(self):
    while not self.stop_event.is_set():
        await asyncio.sleep(3)
        pass  # do stuff

问题是 asyncio.Event 无法等待,所以当它被设置时,在方法完成之前最多等待 3 秒。这是一个问题,因为睡眠时间可能是几分钟。目前,我正在解决这个问题,方法是将 run 包装在 asyncio.Task 中,然后像 event_loop.call_soon(the_task.cancel).

一样取消它

请问有没有更好的方法实现上面的?有没有一种方法可以让我以某种方式等待 asyncio.Event 超时,类似于 threading.Event?

Is there a way I can wait on an asyncio.Event with a timeout somehow, similar to the threading.Event?

asyncio.wait_for 支持方便地向任何等待的协程添加超时。 asyncio.Eventthreading.Event.wait 超时功能的模拟可能如下所示:

async def event_wait(evt, timeout):
    # suppress TimeoutError because we'll return False in case of timeout
    with contextlib.suppress(asyncio.TimeoutError):
        await asyncio.wait_for(evt.wait(), timeout)
    return evt.is_set()

这使得 run 几乎与使用 threading.Event 的那个完全一样:

async def run(self):
    while not await event_wait(self.stop_event, 3):
        pass  # do stuff