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

Tornado≥5版本WebSocket报错RuntimeError:线程无当前事件循环求助

解决Tornado ≥5版本中线程调用WebSocketHandler.write_message的报错问题

这个报错的核心原因是Tornado 5及以上版本切换到了基于asyncio的事件循环模型,每个线程不再自动初始化事件循环,而WebSocketHandler.write_message方法需要在其所属的IOLoop(事件循环)线程中执行,直接在子线程调用会因为找不到当前事件循环而抛出RuntimeError。

修复方案

最安全且兼容所有Tornado版本的做法是:将write_message的调用提交到WebSocketHandler所属的IOLoop线程中执行,利用Tornado的IOLoop.add_callback方法来实现。

修改你的代码如下:

import tornado.httpserver
import tornado.ioloop
import threading
import tornado.web,tornado.websocket

class thr(threading.Thread):
    def __init__(self,handler):
        self.handler=handler
        threading.Thread.__init__(self)
    def run(self):
        # 获取当前handler绑定的IOLoop
        target_io_loop = self.handler.io_loop
        # 将写消息操作提交到该IOLoop的线程中执行
        target_io_loop.add_callback(lambda: self.handler.write_message("test"))

class ClientWebSocketConnectionHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print ("opened")
    def on_message(self, message):
        # 示例:收到消息后启动子线程
        t = thr(self)
        t.start()
    def on_close(self):
        print("closed")

为什么这样有效?

  • WebSocketHandler实例在创建时会绑定到当前的IOLoop(也就是主线程的事件循环),self.handler.io_loop可以直接获取到这个循环。
  • add_callback方法会把传入的函数放到IOLoop的任务队列中,由IOLoop所在的线程(主线程)去执行,这样既避免了线程安全问题,又符合Tornado 5+的事件循环要求。

额外注意事项

  • 不要在子线程中直接操作WebSocketHandler的任何方法,因为这些方法都不是线程安全的,必须通过add_callback提交到对应的IOLoop线程执行。
  • 如果你的代码需要兼容Tornado <5和≥5版本,这种写法完全通用,不需要做版本判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:59:27