Nib*_*Pig 4 c# windows-services signalr .net-core
我可以找到将其添加到 MVC 的教程,甚至从 2014 年开始,就有一篇文章解释了如何将其添加到 .NET 4.7 windows 服务。
然而,对于 .NET Core 3.1 Windows 服务,我只是不知道如何做到这一点。
大多数教程似乎都围绕 Windows 服务中不存在的 Startup.cs 文件。这是我可以从 Microsoft 找到的最新教程,但它使用 Web 应用程序而不是 Windows 服务。
Windows 服务使用以下代码运行:
var builder = new HostBuilder() .ConfigureServices((hostContext, services) => { services.AddHostedService<MyWindowsService>(); });
我认为 SignalR 需要在此处设置。
我找到了一些你可以做的证据,WebApp.Start("http://localhost:8080");但这就是欧文。我找到的示例(上面的示例的旧版本)有一个 Startup 类,但没有指示如何调用该类。它需要一个IAppBuilder并且有一个方法来添加 SignalR。但是 IAppBuilder 似乎不是 .NET Core,我也找不到任何类型的 SignalR 方法。
我想知道是否有人能指出我正确的方向?
小智 6
对于想要开发在 Windows 服务中运行的自托管 ASPNETCore SignalR 中心的人,这里是我的准系统代码。(免责声明:我是 ASPNET Core 的新手,我不知道这种方法是否会被更有知识的人认可。)神奇之处在于“.UseStartup();” 称呼。
使用 VS 2019“Worker Service”C# 模板创建一个新的服务项目。
编辑服务的 .csproj 文件并插入以下行:
<ItemGroup>
<FrameworkReference Include="Microsoft.aspNetCore.App" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
创建一个启动类:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
namespace My.SignalRCore.Service
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddHostedService<Worker>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting(); // pre-requisite for app.UseEndpoints()
app.UseEndpoints(endpoints =>
{
string url = $"/ServerHub";
endpoints.MapHub<MyHub>(url);
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
创建一个 MyHub : Hub 类:
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace My.SignalRCore.Service
{
public class MyHub : Hub
{
public ILogger<Worker> _logger = null;
public MyHub(ILogger<Worker> logger)
{
_logger = logger;
//_logger.LogInformation($"{DateTimeOffset.Now} MyHub.Constructor()");
}
public async Task ProcessClientMessage(string user, string message)
{
// process an incoming message from a connected client
_logger.LogInformation($"{DateTime.Now.ToString("hh:mm:ss.fff")} MyHub.ProcessClientMessage({user}, {message})");
}
}
}
Run Code Online (Sandbox Code Playgroud)
修改 Program 类以使用“UseStartup”调用:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using System;
namespace My.SignalRCore.Service
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseUrls("http://*:12457");
});
}
}
Run Code Online (Sandbox Code Playgroud)
在 Worker 类中添加集线器引用(如果需要):
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace My.SignalRCore.Service
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IHubContext<MyHub> _signalRHub;
public Worker(ILogger<Worker> logger, IHubContext<MyHub> signalRHub)
{
_logger = logger;
_signalRHub = signalRHub;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(15000, stoppingToken);
_logger.LogInformation($"{DateTime.Now.ToString("hh:mm:ss.fff")} Sending ping to all clients");
await _signalRHub.Clients.All.SendAsync("ReceiveMessage", "Server", "ping");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是服务器代码。我尚未将其安装为服务,但它可以作为控制台应用程序运行。在非开发计算机上,您可能需要安装 APSNET CORE 3.1 运行时,可在此处获取: https: //dotnet.microsoft.com/download/dotnet/3.1
对于客户:
安装nuget包:Microsoft.AspNetCore.SignalR.Client
按照以下方式创建客户端类(注意:此处的重新连接代码不起作用):
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;
namespace My.SignalRCoreClientLib
{
public class SignalRCoreClientLib
{
public EventHandler<string> MessageEvent;
private HubConnection _connection;
public async Task Connect(string serverIp, int port)
{
if (_connection == null)
{
_connection = new HubConnectionBuilder()
.WithUrl($"http://{serverIp}:{port}/ServerHub")
.Build();
_connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0, 5) * 1000);
await _connection.StartAsync();
};
_connection.On<string, string>("ReceiveMessage", (user, message) =>
{
string fullMessage = $"{user}: {message}";
MessageEvent?.Invoke(this, fullMessage);
});
}
try
{
await _connection.StartAsync();
}
catch (Exception ex)
{
MessageEvent?.Invoke(this, $"{ex.Message}; base Exception: {ex.GetBaseException().Message}");
await Task.Delay(new Random().Next(0, 5) * 1000);
await Connect(serverIp, port);
}
}
public async Task SendMessage(string user, string message)
{
try
{
await _connection.InvokeAsync("ProcessClientMessage", user, message);
}
catch (Exception ex)
{
MessageEvent?.Invoke(this, ex.Message);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
就是这样。希望这有帮助。