在 Worker Service 项目中使用 SignalR

问题描述 投票:0回答:1

我一直在寻找如何正确配置它的方法,但似乎没有什么对我有用。

我主要关注以下来自 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 个“工作”线程。

enter image description here

c# asp.net-core .net-core signalr background-service
1个回答
0
投票

@Selthien 你找到解决方案了吗?

© www.soinside.com 2019 - 2024. All rights reserved.