我创建了一个继承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);
}
答案 0 :(得分:1)
集线器是短暂的。每次调用集线器方法时,SignalR都会创建一个集线器实例,因此您无法在调用之间的实例属性中存储任何状态。
答案 1 :(得分:0)
我将用于此的属性更改为ConcurrentDictionary,这似乎就是这样做的。它允许我跨所有连接存储客户端连接。我使用了以下代码。
private static readonly ConcurrentDictionary<string, JobRunClient> RunningJobs = new ConcurrentDictionary<string, JobRunClient>();