使用SignalR与Angular实现一对一聊天失败求助
问题定位与修复方案
问题1:手动实例化Hub类(核心错误)
服务中手动new UserHub(_userHubContext)是完全违反SignalR设计规范的操作。SignalR的Hub实例由框架自动管理,手动创建的Hub无法参与连接生命周期的调度,即便传入了IHubContext,也无法正确将消息路由到目标客户端。
修复方案:直接通过注入的IHubContext<UserHub>调用客户端方法,无需实例化Hub类。
问题2:同步阻塞异步操作(死锁隐患)
Hub方法中使用.Wait()阻塞SendAsync的异步执行,在ASP.NET Core环境下,这种同步等待异步任务的写法极易引发线程死锁,导致消息发送流程卡住,服务器无报错但客户端收不到消息。
修复方案:将Hub方法改为异步,用await替代.Wait(),方法返回Task。
问题3:前后端监听参数数量不匹配
服务器端调用SendAsync("GetMessage", message)仅传递1个参数,但客户端监听的是(message: string, connectionId: string)两个参数。SignalR会自动忽略参数数量不匹配的调用,且不会抛出错误,这是客户端收不到消息的直接原因之一。
修复方案:统一前后端参数数量,二选一即可:
- 服务器端补充connectionId参数
- 客户端修改监听逻辑,只接收message参数
修正后代码示例
服务器端服务代码
public class YourSignalrService { private readonly IHubContext<UserHub> _hubContext; // 构造函数注入IHubContext public YourSignalrService(IHubContext<UserHub> hubContext) { _hubContext = hubContext; } public async Task<Response> SendMessageToUser(string connectionId, string message) { // 直接通过上下文调用客户端方法 await _hubContext.Clients.Client(connectionId).SendAsync("GetMessage", message); return new Response { Message = message, IsSuccess = true }; } }
服务器端控制器代码(改为异步)
[HttpPost("SendMessageToUser")] public async Task<IActionResult> SendMessageToUser([FromBody] ChatMessageDto chatMessageDto) { if (chatMessageDto.Validate()) { Response response = await _signalrService.SendMessageToUser(chatMessageDto.ConnectionId, chatMessageDto.Message); return Ok(response); } else { return BadRequest(); } }
客户端SignalR监听代码(匹配参数数量)
public addListenersMsg() { // 和服务器端参数数量保持一致 this.hubConnection.on("GetMessage", (message: string) => { this.messages.push(buildDisplayChatMessageModel(new Date(), message)); }); }
内容的提问来源于stack exchange,提问作者Inbar Manor
相关产品推荐
相关产品推荐

