我如何从单例服务中调用方法以在整个应用程序生命周期中运行 [英] How do i call a method from a singleton service to run throughout the application lifetime

查看:89
本文介绍了我如何从单例服务中调用方法以在整个应用程序生命周期中运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在Net Core中实现了Kafka事件总线作为单例服务.服务本身在Startup.cs中使用Autofac进行配置.该服务具有 Listen()方法:

I have implemented a Kafka event bus as a singleton service in Net Core. The service itself is configured with Autofac in Startup.cs. The service has a Listen() method:

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);
        }
    }
}

我的理解是,为了使此方法在应用程序的生命周期内不断侦听消息,我必须通过某种方式使ServiceProvider与主机关联,然后从Web主机在Program.cs中对其进行调用.服务实例,并调用方法.

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.

我已将我的Program.cs从默认的Net Core 2.1模板配置为以下内容:

I have configured my Program.cs from the default Net Core 2.1 template to the following:

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();
}

除了可以使用主机之外,我还可以通过某种方式访问​​服务,我不知道从这里去哪里.我已经搜索了类似的问题并阅读了官方文档,但似乎无法弄清楚如何访问该服务,以便可以调用 Listen()方法.

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.

这是实现目标的必修"方法吗?如果是这样,我该如何进行?如果不是-也就是说-如果通常以另一种方式完成这种任务,我该如何处理?

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?

推荐答案

以下答案仍然完全正确.Microsoft提供了一个称为 BackgroundService 的基类,可用于仅需实现 ExecuteAsync(CancellationToken StoppingToken)而不是 IHostedService的整个接口的情况下使用.您可以在此处找到它>.为此,您将需要安装软件包 Microsoft.Extensions.Hosting .

The answer below is still perfectly valid. There is a base-class called BackgroundService provided by Microsoft that can be used where you only need to implement ExecuteAsync(CancellationToken stoppingToken) rather than the whole interface of IHostedService. You can find it here. For that you will need to install the package Microsoft.Extensions.Hosting.

先前仍然有效的答案:我建议使用 IHostedService.IHostedService实现被注册为单例,并且一直运行到服务器关闭为止.

Previous and still valid answer: I would suggest to use IHostedService. IHostedService implementations are registered as singletons and they run the whole time until the server shuts down.

创建此基类

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);
}

然后创建消费者主机

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);
            }
        }
    }
}

现在在您的启动类中的ConfigureService方法中添加单例

Now in your startup-class in the ConfigureService method add the singleton

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. No need to manually trigger it, let the webhost do it for you.

这篇关于我如何从单例服务中调用方法以在整个应用程序生命周期中运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆