简体   繁体   English

我如何从单例服务中调用方法以在整个应用程序生命周期中运行

[英]How do i call a method from a singleton service to run throughout the application lifetime

I have implemented a Kafka event bus as a singleton service in Net Core. 我已经在Net Core中将Kafka事件总线实现为单例服务。 The service itself is configured with Autofac in Startup.cs. 服务本身在Startup.cs中使用Autofac进行配置。 The service has a Listen() method: 该服务具有一个Listen()方法:

public void Listen()
{
    using(var consumer = new Consumer<Null, string>(_config, null, new StringDeserializer(Encoding.UTF8)))
    {
        consumer.Subscribe(new string[] { "business-write-topic" });

        consumer.OnMessage += (_, msg) =>
        {
            Console.WriteLine($"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}");
            consumer.CommitAsync(msg);
        };

        while (true)
        {
            consumer.Poll(100);
        }
    }
}

My understanding is that in order for this method to constantly listen for messages during the lifetime of the application, i have to call it in Program.cs from the web host by somehow getting the ServiceProvider associated with the host, then retrieving an instance of the service, and calling the method. 我的理解是,为了使该方法在应用程序的生命周期内不断侦听消息,我必须通过某种方式获取与该主机关联的ServiceProvider,然后从Web主机在Program.cs中对其进行调用。服务,并调用方法。

I have configured my Program.cs from the default Net Core 2.1 template to the following: 我已经将Program.cs从默认的Net Core 2.1模板配置为以下内容:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHost(args);
        host.Run();
    }

    public static IWebHost CreateWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

Beyond having the host available so i can somehow access the services, i don't know where to go from here. 除了可以使用主机之外,我还可以某种方式访问​​服务,我不知道从这里去哪里。 I have searched for similar questions and read around in the official docs but i can't seem to figure out how to access the service so that i can call the Listen() method. 我已经搜索了类似的问题并阅读了官方文档,但似乎无法弄清楚如何访问该服务,以便可以调用Listen()方法。

Is this the "go-to" way of accomplishing my goal? 这是实现目标的“必修”方法吗? If so, how do i proceed? 如果是这样,我该如何进行? And if not - that is - if this kind of task is commonly accomplished in another way, how do i go about it? 如果不是-也就是说-如果通常以另一种方式完成这种任务,我该怎么办?

I would suggest to use IHostedService . 我建议使用IHostedService IHostedService implementations are registered as singletons and they run the whole time until the server shuts down. IHostedService实现注册为单例,它们一直运行直到服务器关闭。

Create this base class 创建此基类

public abstract class HostedService : IHostedService
{
    private Task executingTask;
    private CancellationTokenSource cancellationTokenSource;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        this.cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

        this.executingTask = this.ExecuteAsync(this.cancellationTokenSource.Token);

        return this.executingTask.IsCompleted ? this.executingTask : Task.CompletedTask;
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        if (this.executingTask == null)
        {
            return;
        }

        this.cancellationTokenSource.Cancel();

        await Task.WhenAny(this.executingTask, Task.Delay(-1, cancellationToken));
    }

    protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
}

Then create the consumer-host 然后创建消费者主机

public class ConsumerHost : HostedService
{
    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        using (var consumer = new Consumer<Null, string>(_config, null, new StringDeserializer(Encoding.UTF8)))
        {
            consumer.Subscribe(new string[] {"business-write-topic"});

            consumer.OnMessage += (_, msg) =>
            {
                Console.WriteLine(
                    $"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}");
                consumer.CommitAsync(msg);
            };

            while (!cancellationToken.IsCancellationRequested) // will make sure to stop if the application is being shut down!
            {
                consumer.Poll(100);
                await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
            }
        }
    }
}

Now in your startup-class in the ConfigureService method add the singleton 现在,在您的启动类的ConfigureService方法中,添加单例

public void ConfigureServices(IServiceCollection services)
{
   services.AddSingleton<IHostedService, ConsumerHost>();
}

This service will now kick in when the webhost finished building and stop when you shutdown the server. 现在,该服务将在Webhost完成构建后启动,并在您关闭服务器时停止。 No need to manually trigger it, let the webhost do it for you. 无需手动触发它,让网络托管服务为您完成。

I think BackgroundService is what you need. 我认为BackgroundService是您所需要的。

public class ListnerBackgroundService : BackgroundService
{
    private readonly ListnerService service;

    public ListnerBackgroundService(ListnerService service)
    {
        this.service = service;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        service.Listen();

        return Task.CompletedTask;
    }
}

And register it: 并注册:

public void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddSingleton<IHostedService, ListnerBackgroundService>();
   ...
}

暂无
暂无

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

相关问题 在应用程序的整个生命周期中保持服务的生命周期 - Keeping a service alive throughout the lifetime of the application 如何从服务中调用方法? - How do I call my method from my service? 应用程序生命周期并在 ASP.NET 内核中添加 Singleton DI 服务 - Application Lifetime and Add Singleton DI service in ASP.NET Core 如何在MVC应用程序上运行方法? - How do i run a method on an MVC application? 从AppConfig文件中提取后,如何在整个应用程序中重用连接字符串? - How do I reuse the connection string throughout my application once it has been fetched from the AppConfig file? 如何从WPF应用程序方法运行Windows Service应用程序 - How to run a Windows Service Application from a WPF application method 如何在整个应用程序中创建和注入用户特定的 singleton class? - How to create and inject a user specific singleton class throughout the whole application? 如何注入 IEnumerable<interface> 这也是 singleton 生命周期的托管服务</interface> - How to inject an IEnumerable<Interface> which is also a hosted service as singleton lifetime 在do.net 5 web api项目中,如何在测试方法中获取singleton服务的实例? - In a dotnet 5 web api project, how do I get the instance of a singleton service in a test method? 如何从 MVC 应用程序发出的 WCF 服务调用中获取域\用户名? - How do I fetch the domain\username from a WCF service call made from MVC application?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM