【问题标题】:how to run gather and a coroutine task concurrently如何同时运行收集和协程任务
【发布时间】:2020-12-04 10:17:48
【问题描述】:

我大概有以下代码

import asyncio
.
.
.
async def query_loop()
    while connected:
        result = await asyncio.gather(get_value1, get_value2, get_value3)
        if True in result:
            connected = False

async def main():
    await query_loop()

asyncio.run(main())

get_value - 函数查询设备、接收值并将它们发布到服务器。如果没有出现问题,则返回 False,否则返回 True。

现在我需要实现,get_value2 函数检查它是否收到值 7。在这种情况下,我需要程序等待 3 分钟,然后再向设备发送特殊命令。但与此同时,query_loop 也应该继续。

有人知道怎么做吗? 提前致谢!

【问题讨论】:

    标签: python-3.x multithreading python-asyncio


    【解决方案1】:

    如果我对您的理解正确,您想修改get_value2,以便它通过在后台产生额外的工作来响应从设备接收的值,即在没有query_loop 中的循环的情况下执行某些操作,而不必等待新的工作完成。

    您可以使用asyncio.create_task() 来生成后台任务。其实你可以随时结合create_task()await在后台运行东西; asyncio.gather 只是一个实用功能,可以为您完成。在这种情况下,query_loop 保持不变,get_value2 被这样修改:

    async def get_value2():
        ...
        value = await receive_value_from_device()
        if value == 7:
            # schedule send_command() to run, but don't wait for it
            asyncio.create_task(special_command())
        ...
        return False
    
    async def special_command():
        await asyncio.sleep(180)
        await send_command_to_device(...)
    

    注意如果get_value1等是异步函数,gather的正确调用必须调用它们,所以应该是await asyncio.gather(get_value1(), get_value2(), get_value3())(注意额外的括号)。

    【讨论】:

    • 好的,谢谢您的回答,非常有帮助!但是最后一个问题:你永远不会等待任务“asyncio.create_task(special_command())。即使没有用 await 调用它们,调度的任务也会自动执行吗?
    • @Art3mis 是的,create_task 就是这么做的,你可以把它想象成“在后台等待”。
    • 所以现在我遇到了问题,在循环的每次迭代中都会调用任务 special_command。但我只需要它一次运行一次..
    • @Art3mis special_command 仅在从设备接收到值 7 时调用。如果您需要额外限制时间,可以使用全局变量(或任何其他共享状态变量)来防止多个special_commands 同时运行。答案旨在展示如何生成后台任务,而不是涵盖您的用例的所有细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    相关资源
    最近更新 更多