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
相关产品推荐
相关产品推荐

