You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:39:29