我有一个简单的 SignalR 服务器,我几乎没有使用过。
我的枢纽课程是:
public class MyHub : Hub
{
public List<Player> players { get; set; }
public MyHub()
{
players = new List<Player>();
}
public void Searching(Player player)
{
players.Add(player);
//Clients.All.a
}
}
Run Code Online (Sandbox Code Playgroud)
这是我在代码中调用 Searching 方法和变量的地方
public String UserName { get; set; }
public IHubProxy HubProxy { get; set; }
const string ServerURI = "http://localhost:5051/signalr";
public HubConnection Connection { get; set; }
public Player User { get; set; }
public MainWindow()
{
InitializeComponent();
User = new Player(100);
ConnectAsync();
}
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
HubProxy.Invoke("Searching", User);
}
Run Code Online (Sandbox Code Playgroud)
在 MyHub 类中,我希望玩家列表(现在)跟踪每次有人单击客户端上的 btnSearch 时,通过这样做,我只是将 Player 类的成员添加到 MyHub 中的玩家列表中。
出于某种原因,每次我调用它时,使用调试器我可以看到列表再次为空,再次调用构造函数,玩家列表再次为空。
我在其他堆栈溢出问题中看到问题是静态变量,但我的没有任何内容是静态的。( Player 类中也没有任何内容是静态的)
基本上,集线器是暂时的,这意味着您无法知道实例何时会被回收或丢弃。解决此问题的一种方法是对状态使用单例,但有很多选择。这直接来自 MSDN [1]:
“您无需实例化 Hub 类或从服务器上您自己的代码调用其方法;所有这些都是由 SignalR Hubs 管道为您完成的。SignalR 每次需要处理 Hub 时都会创建一个 Hub 类的新实例操作,例如当客户端连接、断开连接或对服务器进行方法调用时。
因为 Hub 类的实例是瞬态的,所以不能使用它们来维护从一个方法调用到下一个方法调用的状态。每次服务器收到来自客户端的方法调用时,Hub 类的一个新实例都会处理该消息。要通过多个连接和方法调用维护状态,请使用其他一些方法,例如数据库、Hub 类上的静态变量,或者不是从 Hub 派生的其他类。如果在内存中持久化数据,在Hub类上使用静态变量等方法,应用域回收时数据会丢失。
如果要从在 Hub 类之外运行的自己的代码向客户端发送消息,则不能通过实例化 Hub 类实例来实现,但可以通过获取对 Hub 类的 SignalR 上下文对象的引用来实现. 有关详细信息,请参阅本主题后面的如何从 Hub 类外部调用客户端方法和管理组。”
[1]: https ://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-server 《SignalR 文档》