我可以找到将其添加到 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>(); });
我发现了一些你可以做到的证据
WebApp.Start("http://localhost:8080");
但这是 OWIN。我找到的示例(上面的示例的旧版本)有一个 Startup 类,但没有指示如何调用该类。它需要一个
IAppBuilder
并且有一个方法可以添加 SignalR。但是 IAppBuilder 似乎不是 .NET Core,我也找不到任何类型的 SignalR 方法。我想知道是否有人可以指出我正确的方向?
免责声明:我是 ASPNET Core 的新手,我不知道这种方法是否会被更有知识的人认可。)神奇之处在于 .UseStartup<Startup>();
调用。
“Worker Service”C# 模板创建一个新的服务项目。
服务的 .csproj 文件并插入以下行:
<ItemGroup>
<FrameworkReference Include="Microsoft.aspNetCore.App" />
</ItemGroup>
Startup
类:
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);
});
}
}
}
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})");
}
}
}
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");
});
}
}
hub
类中添加
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");
}
}
}
}
https://dotnet.microsoft.com/download/dotnet/3.1
对于客户:
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);
}
}
}
}