You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何持续等待多个并发任务(如多连接套接字)中的任意一个完成?

多套接字持续监控并响应的正确实现方式

要持续监控多个套接字、响应任意一个的可读事件,最优雅且正确的方式是利用asyncio的协程调度特性,避免手动取消待处理任务的低效做法。以下是两种推荐方案:

方案一:为每个套接字创建独立的持续读取协程

这是最简洁的实现方式,每个套接字单独维护自己的读取循环,事件循环会自动调度所有协程,无需手动管理任务列表:

async def read_and_process(sock):
    while True:
        data = await sock.read()
        if not data:
            # 套接字连接关闭,退出循环
            break
        # 处理读取到的数据
        handle_received_data(data)

async def main():
    # 假设已初始化好socket1、socket2等套接字对象
    await asyncio.gather(
        read_and_process(socket1),
        read_and_process(socket2)
    )

每个read_and_process协程会持续等待对应套接字的数据,读取完成后立即处理,随后自动回到等待状态。事件循环会在任意套接字有数据时唤醒对应的协程,完全无需手动干预任务的重新加入。

方案二:动态维护任务集合(适用于需动态增减套接字的场景)

如果需要随时添加或移除监控的套接字,可以维护一个活跃任务集合,处理完成单个套接字的读取后,重新提交该套接字的读取任务,同时保留其他待处理任务(绝对不要取消pending任务):

async def main():
    # 初始化套接字与任务的映射,方便后续关联任务和对应套接字
    sockets = [socket1, socket2]
    task_to_sock = {}
    tasks = set()

    # 初始化为每个套接字创建读取任务
    for sock in sockets:
        task = asyncio.create_task(sock.read())
        task_to_sock[task] = sock
        tasks.add(task)

    while tasks:
        done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)

        for task in done:
            sock = task_to_sock.pop(task)
            try:
                data = task.result()
                if data:
                    # 处理数据
                    handle_received_data(data)
                    # 重新提交该套接字的读取任务,继续监控
                    new_task = asyncio.create_task(sock.read())
                    task_to_sock[new_task] = sock
                    pending.add(new_task)
                else:
                    # 连接关闭,不再监控该套接字
                    print(f"套接字{sock}已关闭")
            except Exception as e:
                # 处理读取异常
                print(f"读取套接字{sock}出错: {str(e)}")

        # 更新任务集合为包含新任务的pending集合
        tasks = pending

为什么你的临时方案有问题

你之前每次循环取消pending任务的做法是错误的:这些pending任务正处于等待其他套接字数据的状态,取消后会导致这些套接字的监控中断,必须重新创建任务才能继续监控,不仅浪费资源,还可能在取消与重建的间隙错过数据,同时会触发不必要的CancelledError异常处理。

内容的提问来源于stack exchange,提问作者JanLikar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:31:05