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

Windows Service连接SignalR服务器失败问题求助

问题分析与解决方案

你的代码存在几个关键问题,导致Windows Service中SignalR回调无法正常工作:

  1. 重复执行连接初始化与事件订阅
    InstallService方法被Timer每5秒调用一次,每次都会重复注册Closed事件、调用StartAsync、订阅InstallService回调。这会导致:

    • 同一回调被多次订阅,可能引发重复执行或内存泄漏
    • 多次调用StartAsync会在连接已打开时抛出异常,中断连接逻辑
    • 重复注册的Closed事件会导致重连逻辑多次触发,引发混乱
  2. 异步操作未等待
    OnStart和InstallService中调用connection.StartAsync()时没有等待完成(火并忘),Windows Service的启动线程不会等待异步操作结束,可能导致连接还未建立就被终止,回调自然无法触发。

  3. 连接状态管理缺失
    没有检查连接当前状态就盲目执行启动操作,导致无效重复调用。


修正后的代码实现

public partial class WindowsServiceManager : ServiceBase
{
    private Timer _timer;
    private HubConnection _connection;
    private readonly object _connectionLock = new object();

    public WindowsServiceManager()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        WriteToFile("Service started at " + DateTime.Now);

        // 初始化SignalR连接(仅执行一次)
        InitializeSignalRConnection();

        // 启动Timer,仅用于周期性业务逻辑(如果需要),而非重复初始化连接
        _timer = new Timer();
        _timer.Elapsed += OnElapsedTime;
        _timer.Interval = 5000;
        _timer.Enabled = true;
    }

    protected override void OnStop()
    {
        WriteToFile("Service stopped at " + DateTime.Now);
        
        // 停止Timer
        _timer?.Stop();
        _timer?.Dispose();

        // 关闭SignalR连接
        if (_connection != null)
        {
            _connection.DisposeAsync().GetAwaiter().GetResult();
        }
    }

    private void InitializeSignalRConnection()
    {
        lock (_connectionLock)
        {
            if (_connection != null && _connection.State == HubConnectionState.Connected)
                return;

            // 创建连接
            _connection = new HubConnectionBuilder()
                .WithUrl("https://localhost:7082/InstallService")
                .Build();

            // 注册Closed事件(仅一次),处理重连逻辑
            _connection.Closed += async (error) =>
            {
                WriteToFile($"Connection closed, error: {error?.Message ?? "None"}. Attempting reconnect...");
                await Task.Delay(new Random().Next(0, 5) * 1000);
                try
                {
                    await _connection.StartAsync();
                    WriteToFile("Reconnected successfully");
                }
                catch (Exception ex)
                {
                    WriteToFile($"Reconnect failed: {ex.Message}");
                }
            };

            // 订阅服务器回调(仅一次)
            _connection.On<string, string>("InstallService", (serviceName, serviceURL) =>
            {
                WriteToFile("Inside SignalR callback");
                WriteToFile($"Service URL: {serviceURL}, Service Name: {serviceName}");
            });

            // 启动连接并等待完成
            try
            {
                _connection.StartAsync().GetAwaiter().GetResult();
                WriteToFile("SignalR connection established successfully");
            }
            catch (Exception ex)
            {
                WriteToFile($"Failed to start SignalR connection: {ex.Message}");
            }
        }
    }

    private void OnElapsedTime(object source, ElapsedEventArgs e)
    {
        WriteToFile("Service recalled at " + DateTime.Now);
        
        // 这里仅执行周期性业务逻辑,比如检查连接状态(可选)
        lock (_connectionLock)
        {
            if (_connection == null || _connection.State != HubConnectionState.Connected)
            {
                WriteToFile("Connection lost, reinitializing...");
                InitializeSignalRConnection();
            }
        }
    }
}

关键修改说明

  • 连接初始化仅执行一次:将连接创建、事件订阅、启动逻辑移到InitializeSignalRConnection方法,通过锁和状态检查避免重复操作。
  • 正确等待异步操作:使用GetAwaiter().GetResult()同步等待StartAsync和DisposeAsync完成,确保连接在服务启动时完全建立,停止时正确关闭。
  • 单一的重连逻辑:仅注册一次Closed事件处理重连,避免重复触发。
  • Timer仅处理周期性检查:Timer不再重复初始化连接,只负责周期性检查连接状态(如果需要),或执行其他业务任务。
  • 线程安全:使用lock确保连接操作的线程安全,避免多线程同时修改连接状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:32:41