无法使用Signalr hub类跟踪连接的用户

时间:2017-09-27 13:56:28

标签: c# asp.net signalr signalr-hub signalr.client

我创建了一个继承Signalr Hub类的类,它在启动时运行。建立连接时,会从客户端发送一些自定义标头,用于生成用户对象。我想将这些存储在服务器的内存中,以便我可以检索列表并在UI中显示它们。然后,有人可以使用此UI查看用户信息并执行与此连接的交互。我在ASP MVC项目中设置了一个集线器类,我正在为客户端使用一个控制台应用程序。我可以很好地连接,服务器可以回传,但是每次向集线器类发出请求时,我在集线器类中用来跟踪连接用户的属性都会重置为null。

public class JobRunHandler : Hub
{
    private List<JobRunClient> RunningJobs { get; set; }

    public JobRunHandler()
    {
        if(this.RunningJobs == null) this.RunningJobs = new List<JobRunClient>();
}

public override Task OnConnected()
{
    JobRunClient runclient = new JobRunClient()
    {
        ConnectionID = Context.ConnectionId,
        Someotherstuff = this.GetHeaderInt(Context.Headers["Someotherstuff"])
    };

    this.RunningJobs.Add(runclient);
    return base.OnConnected();
}

public override Task OnReconnected()
{
    var existingClient = this.GetConnectingClient();
    if (existingClient == null)
    {
        JobRunClient runclient = new JobRunClient()
        {
            ConnectionID = Context.ConnectionId,
            Someotherstuff = this.GetHeaderInt(Context.Headers["Someotherstuff"])
        };

        this.RunningJobs.Add(runclient);
    }
    return base.OnReconnected();
}

public override Task OnDisconnected(bool stopCalled)
{
    this.RemoveClient(Context.ConnectionId);
    return base.OnDisconnected(stopCalled);
}

public void TestMethod()
{
    Clients.All.ping();
    var client = this.GetConnectingClient();
}

}

我已经在每种方法中都设置了断点,所以我知道它何时运行。客户端永远不会断开连接或触发重新连接,因此连接断开没有问题。客户端连接并OnConnected()方法触发,并将值添加到this.RunningJobs。然后客户端调用TestMethod(),但是当我检查this.RunningJobs时它是空的。

Clients.All.ping();运行时,它确实会将ping发送回客户端。因此连接成功,服务器维护连接,我可以在调用单独的方法时将ping发送回客户端,但由于某种原因,属性正在被重置,我不知道为什么。如果必须的话,我可以使用redis,但是我看到其他人使用这种策略并且它不是问题。

这是我为测试它而创建的客户端代码(控制台应用程序)

    var hubConnection = new HubConnection("http://localhost:2497/");
    hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
    IHubProxy myHubProxy = hubConnection.CreateHubProxy("JobRunHandler");

    myHubProxy.On("ping", () => Console.Write("Recieved ping \n"));
    hubConnection.Headers.Add("Someotherstuff", "1");
    hubConnection.Start().Wait();


    while(true)
    {
        myHubProxy.Invoke("BroadcastCompletion").ContinueWith(task =>
        {
            if (task.IsFaulted)
            {
                Console.WriteLine("!!! There was an error opening the connection:{0} \n", task.Exception.GetBaseException());
            }

        }).Wait();
        Console.WriteLine("Broadcast sent to the server.\n");
        Thread.Sleep(4000);
    }

2 个答案:

答案 0 :(得分:1)

集线器是短暂的。每次调用集线器方法时,SignalR都会创建一个集线器实例,因此您无法在调用之间的实例属性中存储任何状态。

答案 1 :(得分:0)

我将用于此的属性更改为ConcurrentDictionary,这似乎就是这样做的。它允许我跨所有连接存储客户端连接。我使用了以下代码。

private static readonly ConcurrentDictionary<string, JobRunClient> RunningJobs = new ConcurrentDictionary<string, JobRunClient>();