【发布时间】:2022-11-12 04:38:09
【问题描述】:
语境:
我目前正在为 Discord 上的机器人编写代码。该机器人内部有一个服务器类(没有花哨的 websockets 和 http 请求)和一个充当用户和服务器之间桥梁的客户端类。客户端类的实例管理向其相应用户发送日志消息、更新其 GUI(这只是一个嵌入和附加到它的一堆按钮)以及调用服务器类上的方法。
目前我被困在日志消息上。当前系统是包含控件的 GUI 消息始终是最近发送的消息。
如果另一个用户要加入服务器类的房间,这将导致 GUI 消息不再更新。此外,将向用户发送一条日志消息,这将导致 GUI 消息不是最近发送的消息。这两个问题都可以通过机器人删除旧的 GUI 消息并在此之后发送更新的消息来解决。
但是,可能会同时加入房间,因此机器人有可能会像这样将更新 GUI 消息的“删除消息”和“发送消息”部分交错:
delete_message()
delete_message() # !!!
send_message()
send_message()
第二个delete_message() 会导致错误,因为它找不到已删除的消息。
我提出的解决方案将是以下问题。
问题:
假设我有一个名为 foo 的异步函数:
import asyncio
limit: int
async def foo():
print("bar")
async def foo_caller():
await asyncio.gather(foo(), foo(), foo(), foo(), foo())
await foo()
await foo()
该函数将使用foo_caller 函数多次调用。目前,这将打印bar7次.
问题是,如何在短时间内多次调用foo 时只执行一个函数调用?
解决方案应仅打印bar三次.一个用于await asyncio.gather(foo(), foo(), foo(), foo(), foo()),一个用于await foo()。
【问题讨论】:
-
它被称为“去抖动”,并用于多种技术。在软件中,当函数被调用时,它会检查一个标志。如果设置了标志,它会立即返回。如果未设置该标志,则设置该标志,启动一个稍后取消设置该标志的计时器,然后继续其操作。
标签: python python-asyncio