微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在应用程序的其他部分获得合适的SignalR集线器?

如何解决如何在应用程序的其他部分获得合适的SignalR集线器?

我正在使用旧的SignalR v2.41,但由于我也仅限于使用旧版本的MVC,因此必须使用它。除此之外,我还使用FluentScheduler定期向客户端发送定向消息。

问题是,我在Hub中保留了一个用户连接字典:

public class MyHub: Hub
{
    public Dictionary<string,User> Connections { get; set; }

    public MyHub()
    {
        Connections = new Dictionary<string,User>();
    }

    public override Task OnConnected()
    {
        // add connection
        return base.OnConnected();
    }

    public override Task Ondisconnected(bool stopCalled)
    {
        // remove connection
        return base.Ondisconnected(stopCalled);
    }
}

现在,在FluentScheduler代码中,我需要掌握连接列表的中心,以便知道将哪个内容发送给哪个连接:

public class MyJob : IJob
{
    public void Execute()
    {
        var hub = new DefaultHubManager(GlobalHost.DependencyResolver).ResolveHub("MyHub") as MyHub;
        foreach (var conn in hub.Connections)
        {
            foreach (var msg in msgs)
            {
                hub.Clients.Client(conn.Key).send(msg);
            }
        }
    }
}

问题是,我使用hub获得的var hub = new DefaultHubManager(GlobalHost.DependencyResolver).ResolveHub("MyHub") as MyHub;实例与客户端连接的实例不同,因为该实例从来没有任何连接。

如何获取正确的集线器实例?

解决方法

new始终是一个新实例,因此您将永远无法获得连接客户端的集线器,因为您创建了一个新的集线器。

您应按以下方式解决中心问题:

static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

您也可以选中此question

编辑:由于您需要向特定用户发送消息,因此我建议实现一个类以添加和删除连接,甚至更好的方法是映射users to groups

建议始终注入IHubContext而不是Hub。引用SignalR开发人员在github上的话

您通常不应该用DI解决集线器。如果需要在集线器和其他组件之间共享代码,建议使用IHubContext或将共享代码放在单独的DI服务中。

此外,您也不应将集线器添加为单例:

SignalR希望分别为每个消息创建集线器。如果希望集线器位于DI中,则需要将其添加为Transient服务。

因为Hub类的实例是瞬态的,所以您不能使用它们来维护从一个方法调用到下一个方法调用的状态。每次服务器从客户端收到方法调用时,您的Hub类的新实例都会处理该消息。要通过多个连接和方法调用维护状态,请使用其他一些方法,例如数据库,Hub类上的静态变量,或者不是从Hub派生的其他类。

有关Hub object lifetime的更多文档。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。