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

Python异步服务循环与Future并发运行,socket服务和PyWin32监控同时运行阻塞如何解决

根因分析

你遇到的两个功能无法同时运行的核心问题是PyWin32的ReadDirectoryChangesW是同步阻塞API,直接在async协程中调用时会完全占用事件循环线程,导致socket服务的任务无法被调度。async协程的并发依赖事件循环的非阻塞调度,任何长时间的同步阻塞调用都会卡住整个循环的所有任务。

解决方案

1. 拆分阻塞逻辑到独立线程

把目录监控里的阻塞调用抽为单独的同步方法,通过async提供的线程桥接方法运行,不占用事件循环主线程。

2. 补充持续监控循环

原有_monitor方法只会执行一次,需要增加无限循环保证持续监听目录变更。

3. 可选优化:替换消息队列实现

标准库queue.Queue是线程安全的,但在异步场景下如果直接调用get()会阻塞事件循环,建议替换为asyncio.Queue,跨线程操作队列时使用loop.call_soon_threadsafe保证线程安全。

代码修改示例

调整目录监控逻辑

# 抽离阻塞的同步监控逻辑
def _sync_monitor(self):
    ReadDirectoryChangesW(
        self._handle,
        self._buffer,
        TRUE,
        (FILE_NOTIFY_CHANGE_SIZE |
         FILE_NOTIFY_CHANGE_ATTRIBUTES |
         FILE_NOTIFY_CHANGE_DIR_NAME |
         FILE_NOTIFY_CHANGE_FILE_NAME |
         FILE_NOTIFY_CHANGE_LAST_WRITE)
    )
    return FILE_NOTIFY_INFORMATION(self._buffer, 9999)

async def _monitor(self):
    while True: # 无限循环保证持续监听
        # Python3.9+ 使用asyncio.to_thread将阻塞调用放到独立线程运行
        change = await asyncio.to_thread(self._sync_monitor)
        # 低于Python3.9版本替换为以下代码
        # loop = asyncio.get_running_loop()
        # change = await loop.run_in_executor(None, self._sync_monitor)
        
        if not change:
            continue
        action, item = change[0]
        act_str = EventWatcher._ACTIONS.get(action)
        chg_msg = {str(time.time()): [str(act_str), item]}
        await self._write_changes(action=action, change=chg_msg)

调整启动逻辑

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) # 绑定当前线程的事件循环,避免上下文异常
loop.create_task(self.handle_traffic())
loop.create_task(self._monitor())
loop.run_forever()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:06:02