[英]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.