如何在Xamarin.Forms中使用3.0+版本SignalR.Client
Xamarin.Forms 使用 3.0+ 版本 Microsoft.AspNetCore.SignalR.Client 配置指南
前置依赖安装
- 共享项目、各平台项目统一安装版本≥3.0的
Microsoft.AspNetCore.SignalR.Client包,优先选择3.1.x这类LTS稳定版,不要安装服务端专属的Microsoft.AspNetCore.SignalR包,避免兼容性冲突 - Android平台提前在
AndroidManifest.xml中添加INTERNET权限;iOS平台如果连接HTTP非加密地址,需要在Info.plist中配置ATS例外,否则系统会拦截连接请求
HubConnection 配置与启动代码示例
以下是可直接在Xamarin.Forms共享项目中使用的封装示例,覆盖连接初始化、生命周期管理、消息收发全流程:
using Microsoft.AspNetCore.SignalR.Client; using System; using System.Threading.Tasks; using Xamarin.Forms; public class SignalRChatService { private HubConnection _hubConnection; // 对外暴露的事件,供页面层绑定更新UI public event Action<string> OnTargetMessageReceived; public event Action<ConnectState> OnConnectStateChanged; public enum ConnectState { Disconnected, Connecting, Connected, Reconnecting } /// <summary> /// 初始化连接配置 /// </summary> /// <param name="hubAddress">SignalR Hub服务端地址</param> /// <param name="token">身份验证令牌(无鉴权可传null)</param> public async Task Initialize(string hubAddress, string token = null) { // 释放已有连接避免资源冲突 if (_hubConnection != null) { await _hubConnection.DisposeAsync(); } // 3.0+版本标准HubConnection构建方式 _hubConnection = new HubConnectionBuilder() .WithUrl(hubAddress, config => { // 注入身份验证令牌 if (!string.IsNullOrWhiteSpace(token)) { config.AccessTokenProvider = () => Task.FromResult(token); } // 适配移动端弱网场景,调高超时阈值 config.CloseTimeout = TimeSpan.FromSeconds(30); }) // 开启内置自动重连,默认重连间隔为0s/2s/10s/30s .WithAutomaticReconnect() .Build(); // 注册连接生命周期回调 _hubConnection.Closed += async _ => { OnConnectStateChanged?.Invoke(ConnectState.Disconnected); // 非主动断开场景延迟5秒后尝试重连 await Task.Delay(5000); await StartConnect(); }; _hubConnection.Reconnecting += _ => { OnConnectStateChanged?.Invoke(ConnectState.Reconnecting); return Task.CompletedTask; }; _hubConnection.Reconnected += newConnectionId => { OnConnectStateChanged?.Invoke(ConnectState.Connected); // 重连后ConnectionId会变更,需同步给服务端更新用户-连接Id绑定关系 return Task.CompletedTask; }; // 注册客户端接收消息的监听,方法名、参数列表必须和服务端定义完全匹配 _hubConnection.On<string>("ReceiveUserMessage", msg => { // SignalR回调默认不在UI线程,更新控件需切到主线程 Device.BeginInvokeOnMainThread(() => { OnTargetMessageReceived?.Invoke(msg); }); }); await StartConnect(); } // 启动连接 private async Task StartConnect() { if (_hubConnection.State == HubConnectionState.Connected) return; try { OnConnectStateChanged?.Invoke(ConnectState.Connecting); await _hubConnection.StartAsync(); OnConnectStateChanged?.Invoke(ConnectState.Connected); // 连接建立后可获取当前客户端的ConnectionId var currentConnId = _hubConnection.ConnectionId; } catch (Exception e) { OnConnectStateChanged?.Invoke(ConnectState.Disconnected); Console.WriteLine($"SignalR连接失败:{e.Message}"); } } /// <summary> /// 向指定ConnectionId的用户发消息(3.0+版本原生支持该能力) /// </summary> public async Task SendToTarget(string targetConnectionId, string content) { if (_hubConnection.State != HubConnectionState.Connected) { throw new InvalidOperationException("连接未就绪,无法发送消息"); } // 调用服务端Hub方法,服务端内部直接用 Clients.Client(targetConnectionId).SendAsync("ReceiveUserMessage", content) 即可完成定向推送,不需要1.x版本的自定义映射逻辑 await _hubConnection.InvokeAsync("SendToSpecifiedUser", targetConnectionId, content); } // 应用退出/页面销毁时调用释放资源 public async Task Release() { if (_hubConnection != null) { await _hubConnection.StopAsync(); await _hubConnection.DisposeAsync(); } } }
关键注意事项
- 所有SignalR异步方法必须使用
await调用,禁止用.Wait()、.Result做同步阻塞,否则Xamarin平台极易出现线程死锁 - 自动重连成功后客户端ConnectionId会刷新,如果服务端维护了用户和ConnectionId的映射表,必须在
Reconnected事件触发后将新Id同步给服务端,否则定向推送会失效 - 建议将SignalR服务注册为全局单例,不要在单个页面中声明局部HubConnection实例,避免页面销毁导致连接意外断开
- 移动端网络切换(WiFi切移动数据、网络波动断网)场景下,内置自动重连可能失效,可根据业务需要增加手动重连逻辑
内容的提问来源于stack exchange,提问作者solarispirozi
相关产品推荐
相关产品推荐

