SignalR 2事件处理方法运行一段时间后不再触发的问题
SignalR 2 客户端事件处理方法一段时间后停止触发的问题
我基于SignalR 2实现的应用启动初期运行正常,但运行一段时间(5到30分钟不等)后,NewMessage事件处理方法不再被调用。经确认,服务器与客户端仍保持连接:客户端SignalR日志显示仍能接收服务器指令,客户端发送的消息也能被服务器接收并执行,连接状态检查结果也正常。
以下是我的实现代码:
public void ConnectAsync() { WriteToLogs("Connecting to Server..."); var dic = new Dictionary<string, string> { { "UserName", _signalrSettings.ApplicationName } }; _hubConnection?.Dispose(); _hubConnection = new HubConnection(_signalrSettings.ServerUri, dic); _hubConnection.StateChanged += Connection_StateChanged; _hubProxy = _hubConnection.CreateHubProxy(_signalrSettings.HubProxy); try { _hubProxy.On<string, string>("Initial", (a, b) => Initial()); _hubConnection.Start().ContinueWith((s) => { if (s.IsCompleted) { _isCompleted = true; } else if (s.IsCanceled) { _isCompleted = false; } else if (s.IsFaulted) { _isCompleted = false; } _hubProxy.On<string, string>("NewMessage", (userName, message) => NewMessage(userName, message)); // 一段时间后该事件不再触发 WriteToLogs( $@"Connection status is {_hubConnection.State}"); }).Wait(); } catch (Exception e) { var trace = new StackTrace(e, true); var reflectedType = trace.GetFrame(0).GetMethod().ReflectedType; if (reflectedType != null) { _messageOperation.WriteErrors($@"Error {e.StackTrace} at {trace}"); } } }
问题原因
核心问题在于事件注册的时机错误:你把NewMessage事件的注册放在了Start()的ContinueWith回调里。SignalR连接如果发生自动重连(即使你没手动写重连逻辑,底层也可能因网络波动触发重连),重连会重建连接上下文,而ContinueWith回调只在第一次启动成功时执行一次,重连后不会再触发这个回调,导致NewMessage事件没有被重新注册,自然不会再触发。
另外,ContinueWith的回调在后台线程执行,虽然SignalR客户端API大多线程安全,但事件注册逻辑放在这里也存在潜在的线程安全风险。
解决方案
1. 统一事件注册时机(核心修复)
把所有事件注册(包括Initial和NewMessage)移到_hubConnection.Start()之前,这样每次创建连接时都会重新绑定事件处理方法,即使后续重连,只要重新初始化连接,事件就会被重新注册。
修改后的代码:
public void ConnectAsync() { WriteToLogs("Connecting to Server..."); var dic = new Dictionary<string, string> { { "UserName", _signalrSettings.ApplicationName } }; _hubConnection?.Dispose(); _hubConnection = new HubConnection(_signalrSettings.ServerUri, dic); _hubConnection.StateChanged += Connection_StateChanged; _hubProxy = _hubConnection.CreateHubProxy(_signalrSettings.HubProxy); try { // 所有事件注册移到连接启动前,确保每次初始化连接都绑定 _hubProxy.On<string, string>("Initial", (a, b) => Initial()); _hubProxy.On<string, string>("NewMessage", (userName, message) => NewMessage(userName, message)); _hubConnection.Start().ContinueWith((s) => { if (s.IsCompleted) { _isCompleted = true; } else if (s.IsCanceled) { _isCompleted = false; } else if (s.IsFaulted) { _isCompleted = false; } WriteToLogs( $@"Connection status is {_hubConnection.State}"); }).Wait(); } catch (Exception e) { var trace = new StackTrace(e, true); var reflectedType = trace.GetFrame(0).GetMethod().ReflectedType; if (reflectedType != null) { _messageOperation.WriteErrors($@"Error {e.StackTrace} at {trace}"); } } }
2. 补充重连逻辑(可选)
如果你的客户端需要处理网络波动导致的断开,可以监听StateChanged事件,当连接从Disconnected切换到Connecting时,重新调用ConnectAsync方法,确保每次重连都能重新初始化连接并注册事件。
内容的提问来源于stack exchange,提问作者Ibanez1408
相关产品推荐
相关产品推荐

