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

如何让SignalR控制台客户端自动重连?问题排查求助

问题原因与解决方案

核心原因:WithAutomaticReconnect() 的行为特性

你使用了 .WithAutomaticReconnect(),SignalR 默认会自动尝试重连4次,间隔分别为0秒、2秒、10秒、30秒。只有当所有自动重连尝试都失败后,才会触发 Closed 事件。因此网站刚下线时,客户端还处于重试阶段,不会触发 Closed,自然看不到"Connection Lost"日志。

另外,你初始的 try-catch 仅包裹了第一次启动连接的代码,后续连接断开后的错误不会被这个 catch 捕获,所以也不会输出"Failed to connect to Website"。

修正方案

1. 监控重连全过程(保留自动重连)

添加 Reconnecting 和 Reconnected 事件,实时监控重连状态:

public class MyBot
{
    HubConnection connection;

    public async Task RunAsync()
    {
        try
        {
            connection = new HubConnectionBuilder()
                .WithUrl("https://localhost:7178/MyHub")
                .WithAutomaticReconnect()
                .Build();

            // 开始重连时触发
            connection.Reconnecting += (error) =>
            {
                Console.WriteLine($"正在尝试重连,错误原因:{error?.Message}");
                return Task.CompletedTask;
            };

            // 重连成功时触发
            connection.Reconnected += (connectionId) =>
            {
                Console.WriteLine($"重连成功,新连接ID:{connectionId}");
                return connection.InvokeAsync("JoinBots");
            };

            // 所有重连尝试失败后触发
            connection.Closed += async (error) =>
            {
                Console.WriteLine("所有重连尝试失败,连接已关闭");
                await Task.Delay(new Random().Next(0, 5) * 1000);
                try
                {
                    await connection.StartAsync();
                    await connection.InvokeAsync("JoinBots");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"手动重连失败:{ex.Message}");
                }
            };

            connection.On<string, string>("DoSomething", (arg1, arg2) =>
            {
                //Do Something
            });

            await connection.StartAsync();
            await connection.InvokeAsync("JoinBots");
            Console.WriteLine("初始连接成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"初始连接失败:{ex.Message}");
        }
    }
}

2. 自定义重连逻辑(关闭自动重连)

若想完全自主控制重连流程,可去掉 .WithAutomaticReconnect(),直接在 Closed 事件中处理:

public class MyBot
{
    HubConnection connection;

    public async Task RunAsync()
    {
        try
        {
            connection = new HubConnectionBuilder()
                .WithUrl("https://localhost:7178/MyHub")
                // 去掉自动重连,自定义逻辑
                .Build();

            connection.Closed += async (error) =>
            {
                Console.WriteLine($"连接断开,错误原因:{error?.Message}");
                // 无限重试直到连接成功
                while (true)
                {
                    try
                    {
                        await Task.Delay(new Random().Next(0, 5) * 1000);
                        await connection.StartAsync();
                        await connection.InvokeAsync("JoinBots");
                        Console.WriteLine("重连成功");
                        break;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"重连失败,将重试:{ex.Message}");
                    }
                }
            };

            connection.On<string, string>("DoSomething", (arg1, arg2) =>
            {
                //Do Something
            });

            await connection.StartAsync();
            await connection.InvokeAsync("JoinBots");
            Console.WriteLine("初始连接成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"初始连接失败:{ex.Message}");
        }
    }
}

关键注意点

  • 异步事件处理程序(如 Closed)内部必须添加 try-catch,否则异常会被静默吞掉,无法查看错误信息。
  • 若使用自动重连,可通过 .WithAutomaticReconnect(new int[] { 0, 2000, 10000, 30000 }) 自定义重试间隔,或实现 IRetryPolicy 接口完全自定义重试逻辑。

内容的提问来源于stack exchange,提问作者Bagzli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:39:25