繁体   English   中英

在 ASP.NET 核心 3 中使用来自单独 class 的集线器

[英]Using Hub from separate class in ASP.NET Core 3

我正在开发一个程序,我从 SignalR 接收数据,执行处理,然后在处理完成后将 SignalR 消息发送回客户端。 我找到了一些关于如何做到这一点资源,但我不太清楚如何在我的项目中实现它。

这是我的代码的样子:

自举


    public static void Main(string[] args)
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        List<ISystem> systems = new List<ISystem>
        {
            new FirstProcessingSystem(),
            new SecondProcessingSystem(),
        };
        Processor processor = new Processor(
            cancellationToken: cancellationTokenSource.Token,
            systems: systems);
        processor.Start();
        CreateHostBuilder(args).Build().Run();
        cancellationTokenSource.Cancel();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<TestHub>("/testHub");
            });
        }
    }

测试集线器.cs


    public class TestHub : Hub
    {
        public async Task DoStuff(Work work)
        {
            FirstProcessingSystem.ItemsToProcess.Add(work);
        }
    }

工作.cs


    public class Work
    {
        public readonly string ConnectionId;
        public readonly string Data;

        public Work(string connectionId, string data)
        {
            ConnectionId = connectionId;
            Data = data;
        }
    }

处理器.cs

    public class Processor
    {
        readonly CancellationToken CancellationToken;
        readonly List<ISystem> Systems;

        public Processor(
            CancellationToken cancellationToken,
            List<ISystem> systems)
        {
            CancellationToken = cancellationToken;
            Systems = systems;
        }

        public void Start()
        {
            Task.Run(() =>
            {
                while (!CancellationToken.IsCancellationRequested)
                {
                    foreach (var s in Systems)
                        s.Process();
                }
            });
        }
    }

系统


    public interface ISystem
    {
        void Process();
    }

    public class FirstProcessingSystem : ISystem
    {
        public static ConcurrentBag<Work> ItemsToProcess = new ConcurrentBag<Work>();

        public void Process()
        {
            while (!ItemsToProcess.IsEmpty)
            {
                Work work;
                if (ItemsToProcess.TryTake(out work))
                {
                    // Do things...
                    SecondProcessingSystem.ItemsToProcess.Add(work);
                }
            }
        }
    }

    public class SecondProcessingSystem : ISystem
    {
        public static ConcurrentBag<Work> ItemsToProcess = new ConcurrentBag<Work>();

        public void Process()
        {
            while (!ItemsToProcess.IsEmpty)
            {
                Work work;
                if (ItemsToProcess.TryTake(out work))
                {
                    // Do more things...
                    // Hub.Send(work.ConnectionId, "Finished");
                }
            }
        }
    }

我知道我可以在 Hub 中执行处理,然后发回“已完成”调用,但我想将我的处理与入站消息分离,这样我可以在需要时添加更多ISystems

有人可以请这个吗? (另外,如果有人有更好的方法来构建我的程序,我也会感谢反馈)

aspnet有一个非常强大的依赖注入系统,你为什么不用呢? 通过在没有依赖注入的情况下创建工作服务,您将很难使用 aspnet 提供的任何东西。

由于您的“处理系统”似乎是长时间运行的服务,您通常会让它们实现IHostedService ,然后创建一个通用服务启动器(取自此处):

public class BackgroundServiceStarter<T> : IHostedService where T : IHostedService
{
    readonly T _backgroundService;

    public BackgroundServiceStarter(T backgroundService)
    {
        _backgroundService = backgroundService;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        return _backgroundService.StartAsync(cancellationToken);
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return _backgroundService.StopAsync(cancellationToken);
    }
}

然后将它们注册到ConfigureServices的 DI 容器中:

// make the classes injectable
services.AddSingleton<FirstProcessingSystem>();
services.AddSingleton<SecondProcessingSystem>();

// start them up
services.AddHostedService<BackgroundServiceStarter<FirstProcessingSystem>>();
services.AddHostedService<BackgroundServiceStarter<SecondProcessingSystem>>();

现在您已正确设置所有内容,您可以使用IHubContext<TestHub> context在需要它的任何 class 的构造函数参数中简单地注入对 signalR 集线器的引用(如您发布的一些链接中所述)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM