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

SignalR不同Hub之间如何通信?Jackbox类互动游戏开发相关问题

问题根因

你碰到的报错本质是使用方式不符合SignalR的设计规范:SignalR的Hub实例是瞬态生命周期,仅在处理客户端单次请求/连接事件时创建,请求处理完成后就会被立即销毁。你在瞬态的Hub实例中订阅单例ServerManager的事件,会导致两个问题:

  1. 事件触发时Hub实例已经被释放,Clients上下文不存在,抛出访问已释放对象的报错
  2. 单例事件会持有Hub实例的引用,导致Hub实例无法被GC回收,引发内存泄漏,还会出现同一事件被多次触发的异常情况

推荐解决方案:使用IHubContext实现跨Hub通信

这是SignalR官方提供的标准跨Hub/跨服务发消息方案,IHubContext是单例生命周期,不会随请求销毁,用法和Hub内的Clients完全一致。

具体改造步骤:

  1. 将事件订阅和处理逻辑从Hub中迁移到单例ServerManager中,在ServerManager中注入对应Hub的IHubContext
public class ServerManager
{
    private readonly IHubContext<HostHub> _hostHubContext;
    // 原有单例实现逻辑保留,改造构造函数注入IHubContext
    private ServerManager(IHubContext<HostHub> hostHubContext)
    {
        _hostHubContext = hostHubContext;
        // 事件订阅逻辑移到单例内部
        OnPlayerJoinedRoom += ServerManager_OnPlayerJoinedRoom;
    }

    public event EventHandler<(string hostConnectionId, string playerId, string playerName)> OnPlayerJoinedRoom;

    private void ServerManager_OnPlayerJoinedRoom(object sender, (string hostConnectionId, string playerId, string playerName) info)
    {
        // 用注入的IHubContext发消息,无对象释放问题
        _hostHubContext.Clients.Client(info.hostConnectionId)
            .SendAsync("PlayerJoined", Extensions.ParamArray(info.playerId, info.playerName));
    }

    // 原有ServerManager其他逻辑保留
}
  1. 在服务注册时,通过工厂方法为单例ServerManager注入IHubContext
// 先注册SignalR服务
builder.Services.AddSignalR();
// 注册ServerManager单例,注入所需的IHubContext
builder.Services.AddSingleton<ServerManager>(serviceProvider => 
{
    var hostHubContext = serviceProvider.GetRequiredService<IHubContext<HostHub>>();
    // 如果需要给GameHub客户端发消息,同理注入IHubContext<GameHub>即可
    return new ServerManager(hostHubContext);
});

其他可选方案

如果你的业务逻辑复杂度较高,可以将所有跨端通信的公共逻辑抽为独立的业务服务,两个Hub仅负责处理各自客户端的连接、消息收发,不承载业务逻辑,所有业务操作都调用公共服务完成,从架构层面避免Hub之间的直接通信需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:15:03