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

如何在async def上下文外调用asyncio.Event.set()?解决按钮点击阻塞问题

问题修正方案

问题根源

你的代码中asyncio.run(waiter(event1))会启动独立的asyncio事件循环并阻塞主线程,直到waiter协程执行完毕。而ipywidgets的按钮点击事件依赖主线程的UI事件循环处理,主线程被阻塞后,点击操作的回调函数根本无法执行,自然无法触发event1.set()。

另外,event_done是异步函数,但ipywidgets的on_click期望传入同步回调,直接传入异步函数不会被正确调度执行。

修正后的代码

import asyncio
from ipywidgets import Button

def event_done(btn):
    event1.set()
    print('registred a click')
    
run_button = Button(description='continue')
run_button.on_click(event_done)

event1 = asyncio.Event()
async def waiter(event1):
    print('waiting')
    await event1.wait()
    print("After waiting")

display(run_button)
await waiter(event1)

关键修改点

  1. 替换asyncio.run为直接await:Jupyter环境本身已经运行着一个asyncio事件循环,直接await waiter(event1)不会阻塞主线程,UI事件可以正常响应。
  2. 将异步回调改为同步函数:event.set()是同步操作,不需要异步回调,直接用普通函数作为按钮点击的处理逻辑即可。如果确实需要在回调中执行异步操作,可以用asyncio.create_task()包装异步代码,示例如下:
    def event_done(btn):
        asyncio.create_task(async_set_event())
    
    async def async_set_event():
        await asyncio.sleep(0.1)  # 模拟异步操作
        event1.set()
        print('registred a click')
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:35:18