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

.NET 4.8客户端用AspNetCore.SignalR.Client连Windows Service SignalR失败

问题描述

我已在Windows Service中成功创建SignalR连接且运行正常,但在.NET 4.8桌面应用中使用Microsoft.AspDotNet.SignalR.Client连接时,启动连接环节一直卡住无法完成。

服务端基于.NET 4.8,代码如下:
Windows Service启动代码:

var _ServiceSignalR = WebApp.Start<Startup>("http://localhost:8585");
var ServiceHubContext = GlobalHost.ConnectionManager.GetHubContext<ServiceHub>();

Startup.cs:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR(new HubConfiguration { EnableDetailedErrors = true});
    }
}

ServiceHub.cs:

[HubName("ServiceHub")]
public class ServiceHub : Hub
{
    public override Task OnConnected()
    {
        // 应该能进入这里
        return base.OnConnected();
    }
}

客户端同样基于.NET 4.8,使用AspNetCore.SignalR.Client的代码:

var serviceHubConnectionx = new HubConnectionBuilder()
    .WithUrl("http://localhost:8585/signalr")
    .Build();
await serviceHubConnectionx.StartAsync(); // 这里一直卡住!

我尝试使用AspNet.SignalR.Client创建Hub代理,连接可立即成功,但该客户端无AspNetCore版本的特性(如程序关闭时触发OnDisconnected、客户端方法返回值等),因此希望使用AspNetCore.SignalR.Client。请问在此场景下是否有可行方案?

原因分析

核心问题是传统ASP.NET SignalR(Microsoft.AspNet.SignalR)和ASP.NET Core SignalR是完全不兼容的两个框架:

  • 服务端用的是传统SignalR,它的路由规则、通信协议和ASP.NET Core SignalR完全不同
  • 用ASP.NET Core SignalR Client连接传统SignalR服务端时,两者无法协商出可用的通信方式,导致连接卡住
可行方案

方案1:将服务端升级为ASP.NET Core SignalR(兼容.NET Framework 4.8)

.NET Framework 4.8支持运行ASP.NET Core应用,把Windows Service中的SignalR服务替换为ASP.NET Core版本后,就能和ASP.NET Core SignalR Client正常通信,步骤如下:

  1. 移除服务端原有的Microsoft.AspNet.SignalR相关NuGet包,安装Microsoft.AspNetCore.SignalR和Microsoft.AspNetCore.Owin
  2. 修改Windows Service的SignalR启动代码:
// 替换原WebApp.Start方式,使用ASP.NET Core WebHost托管
var host = WebHost.CreateDefaultBuilder()
    .UseUrls("http://localhost:8585")
    .ConfigureServices(services =>
    {
        // 配置Cors
        services.AddCors(options =>
        {
            options.AddPolicy("AllowAll", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader()
                       .AllowCredentials();
            });
        });
        // 注册SignalR服务
        services.AddSignalR();
    })
    .Configure(app =>
    {
        app.UseCors("AllowAll");
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            // 配置Hub的路由
            endpoints.MapHub<ServiceHub>("/serviceHub");
        });
    })
    .Build();

host.Start();
// 获取HubContext的方式更新为ASP.NET Core的依赖注入方式
var serviceHubContext = host.Services.GetRequiredService<IHubContext<ServiceHub>>();
  1. 修改ServiceHub代码(ASP.NET Core SignalR不再需要[HubName]特性,默认使用类名):
public class ServiceHub : Hub
{
    public override Task OnConnectedAsync()
    {
        // 连接建立时触发
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        // 连接断开时触发(包括程序关闭场景)
        return base.OnDisconnectedAsync(exception);
    }
}
  1. 客户端连接代码调整路由:
var serviceHubConnectionx = new HubConnectionBuilder()
    .WithUrl("http://localhost:8585/serviceHub")
    .Build();
await serviceHubConnectionx.StartAsync(); // 现在可以正常完成连接

方案2:保留传统SignalR服务端,手动实现所需特性

如果无法升级服务端,只能继续使用传统SignalR Client,但可以手动模拟你需要的ASP.NET Core SignalR特性:

1. 程序关闭时触发断开事件

在桌面应用的退出逻辑中手动调用连接停止方法,同时订阅客户端的Closed事件处理断开场景:

var hubConnection = new HubConnection("http://localhost:8585/signalr");
var hubProxy = hubConnection.CreateHubProxy("ServiceHub");

// 订阅连接断开事件
hubConnection.Closed += async () =>
{
    // 这里处理断开后的逻辑,比如记录日志或尝试重连
    await Task.Delay(1000);
    // 可选:自动重连
    await hubConnection.Start();
};

await hubConnection.Start();

// 在程序退出时(比如FormClosing事件中)主动停止连接
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
    hubConnection.Stop().Wait();
}

2. 客户端方法返回值

传统SignalR支持客户端调用服务端方法获取返回值,若需要服务端调用客户端方法时获取返回值,可以通过回调方式实现:

// 服务端代码
public async Task RequestClientData(string callbackId)
{
    // 通知客户端需要返回数据,并传入回调ID
    await Clients.Caller.SendAsync("ProvideData", callbackId);
}

// 服务端接收客户端返回结果的方法
public void ReceiveClientResult(string callbackId, string result)
{
    // 处理客户端返回的数据
}

// 客户端代码
hubProxy.On<string>("ProvideData", async callbackId =>
{
    var clientData = "客户端生成的数据";
    // 调用服务端方法返回结果
    await hubProxy.InvokeAsync("ReceiveClientResult", callbackId, clientData);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:13:16