我一直在寻找如何正确配置它的方法,但似乎没有什么对我有用。
我主要关注以下来自 Microsoft 的文章,并根据自己的需求进行调整。
使用.Net 5.0
对于初学者来说,我想做的是在我的 Web UI 和我的 BackgroundService 之间创建一个 SignalR 连接。创建后台服务时,我使用 File -> New Project -> Worker Service 模板来创建此服务。我需要能够在后台服务中向客户端发送数据并从客户端接收数据。
程序.cs
这里我添加了SignalR。这看起来很简单。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("myContext")));
services.AddSignalR();
services.AddHostedService<Worker>();
});
}
界面:
这就是我的理解开始崩溃的地方。我想这是一个向客户端发送数据的接口?
public interface IDesoutterController
{
Task SendData(DateTime currentTime);
}
控制器中心:
这是我的中心,包含在工作人员服务项目中,具有向所有客户端发送数据的功能。
public class ControllerHub : Hub<IDesoutterController>
{
public async Task SendDataToClients(DateTime dateTime)
{
await Clients.All.SendData(dateTime);
}
}
Controller Hub 客户端:
这是我最困惑的地方。为什么我的服务使用集线器和集线器客户端,或者这都是糟糕的措辞?这只是从我的 Web UI 接收数据的部分吗?我的 Web UI 项目会调用端点 /hubs/controller 吗??
public partial class ControllerHubClient : IDesoutterController, IHostedService
{
private readonly ILogger<ControllerHubClient> _logger;
private HubConnection _connection;
public ControllerHubClient(ILogger<ControllerHubClient> logger)
{
_logger = logger;
_connection = new HubConnectionBuilder()
.WithUrl("/hubs/controller")
.Build();
_connection.On<DateTime>("onSend", SendData);
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// Loop is here to wait until the server is running
while (true)
{
try
{
await _connection.StartAsync(cancellationToken);
break;
}
catch
{
await Task.Delay(1000);
}
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return _connection.StopAsync();
}
public Task SendData(DateTime currentTime)
{
_logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());
return Task.CompletedTask;
}
}
工人服务:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IHubContext<ControllerHub, IDesoutterController> _controllerHub;
public Worker(ILogger<Worker> logger, IHubContext<ControllerHub, IDesoutterController> controllerHub)
{
_logger = logger;
_controllerHub = controllerHub;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//Other Stuff
}
}
}
实际上,我想做的就是在 Web UI 和 Worker Service 项目之间建立 SignalR 连接,以允许(快速)发送事件。我的后台服务的每个实例都需要自己的集线器。当然,我相当确定我做的这一切都是错误的。然而,每当我启动我的工人服务项目时,我都会收到以下错误。
System.TypeLoadException:程序集“Microsoft.AspNetCore.SignalR.Core,Version=1.1.0.0,Culture=neutral,PublicKeyToken=adb9793829ddae60”中类型“Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1”中的“方法“GetStreamItemType”没有实施。'
任何帮助或指导将不胜感激,因为我对后台服务和信号器完全陌生。
编辑
这是我正在尝试创建的系统的示意图。在阅读了一些评论后,我想澄清我的工作服务项目没有startup.cs(这是我阅读微软文章时感到困惑的一个重要原因)。我想是因为我使用了工人服务模板?就我而言,我“认为”我试图将客户端和中心放在同一个项目中。 在评论中提出另一个建议后,我相信我希望在我的 Web UI 项目中使用集线器,并使我的后台服务客户端连接到集线器?
因此,在图片中将 UI 切换为集线器,将后台工作人员服务切换为客户端?当我说工作人员服务时,我的意思是我正在为每个设备创建一个任务。因此每个设备有 1 个“工作”线程。
@Selthien 你找到解决方案了吗?