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

KeyboardInterrupt触发时thread.join()报错问题求助

问题分析

你遇到的错误根源是:捕获KeyboardInterrupt后仅打印提示,未正确停止后台线程中的asyncio事件循环,导致thread.join()持续阻塞。此时若再次触发中断(比如重复按Ctrl+C),就会在join()调用时抛出异常。

解决方案

要实现优雅终止,需在捕获中断信号后先安全停止后台事件循环,再等待线程结束:

  • 用event_loop.call_soon_threadsafe(event_loop.stop)在主线程中通知后台事件循环停止(事件循环运行在其他线程,必须用线程安全的方式调用)
  • 若需要等待foo任务完成后再退出,可额外添加任务取消或等待逻辑
  • 最后调用thread.join()等待线程正常退出
修正后的代码
import threading
import asyncio
import sys
import time

def callback_handler(name):
    print(f"Hi im a callback_handler, my name is {name}")

async def foo(name, cb):
    await asyncio.sleep(5)
    print("Inside foo")
    if cb:
        await asyncio.sleep(5)
        # 同步回调建议放到线程池执行,避免阻塞事件循环
        await asyncio.get_event_loop().run_in_executor(None, cb, name)

event_loop = asyncio.new_event_loop()
task = event_loop.create_task(foo("bar", callback_handler))
thread = threading.Thread(target=event_loop.run_forever, daemon=True)
thread.start()

try:
    while True:
        message = input("> ")
except (KeyboardInterrupt, EOFError):
    print('Received KeyboardInterrupt')
    # 线程安全地停止事件循环
    event_loop.call_soon_threadsafe(event_loop.stop)
    # 可选:若需要取消当前任务,可添加以下代码
    # event_loop.call_soon_threadsafe(task.cancel)

thread.join()
print("Program exited gracefully")
额外说明
  • 同步回调直接在async函数中调用会阻塞事件循环,用run_in_executor放到线程池执行能避免影响其他异步任务
  • 标记线程为daemon=True后,主线程退出时守护线程会自动终止,但主动停止事件循环能实现更可控的优雅退出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:55:23