.net 核心辅助角色服务中的多个辅助角色?



点网核心 3.0 工作线程服务模板如下所示:

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
});
}

"Worker"类派生自BackgroundService。它循环每 1000 毫秒将日志写入控制台。

我的问题:

我可以同时运行多个"辅助角色"吗?(我知道我可以创建另一个类"Worker2"。但是我可以运行同一类"Worker"的两个副本吗?

如果是,我如何配置两个具有不同配置或参数的"工作线程",例如两个具有不同循环间隔的 Workers?(因为"worker"类的实例是由 DI 框架创建的。我不知道如何将不同的配置/参数传递给"worker"的两个不同实例(

你可以有一个"父"工作线程来启动这样的"真正的"工作线程......

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var workers = new List<Task>();
foreach(var delay in _config.LoopIntervals)
workers.Add(DoRealWork(delay, stoppingToken));
await Task.WhenAll(workers.ToArray());
}
}

然后。。。

private async Task DoRealWork(int delay, CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("worker {delay} checking in at {time}", delay, DateTimeOffset.Now);
await Task.Delay(delay, stoppingToken);
}
}

_config从 appSettings.json 填充并像这样传递给 Worker 的构造函数......

var cfg = hostContext.Configuration.GetSection(nameof(WorkerConfig)).Get<WorkerConfig>();
services.AddSingleton(cfg);
services.AddHostedService<Worker>();

和应用程序设置...

{
"WorkerConfig": {
"LoopIntervals": [ 1000, 2000, 3000 ]
}
}

"AddHostedService"不接受两次注册的同一类的原因:

我检查了"AddHostedService"的github源代码,发现它的实现方式如下:

services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());

根据"TryAddEnumerable"方法Microsoft文档,仅当集合不包含相同服务和实现类型的其他注册时,才会添加服务。这就是我无法运行"工人"的两个副本的原因。 ("TryAddEnumerable"是有意使用的,以避免为同一服务创建多个实例 https://github.com/aspnet/Extensions/issues/1078。


溶液:

所以我可以直接使用"添加单例"添加两个工人......

services.AddSingleton<IHostedService, Worker>();
services.AddSingleton<IHostedService, Worker>();

它有效。


将参数传递给服务构造函数:

然后,我通过为循环间隔添加第二个参数来修改 Worker 类构造函数。最后,我在注册服务时使用实现工厂如下

services.AddSingleton<IHostedService>(sp => new Worker(sp.GetService<ILogger<Worker>>(), 1000));
services.AddSingleton<IHostedService>(sp => new Worker(sp.GetService<ILogger<Worker>>(), 2000));

嗨,我也在寻找运行后台服务多个实例的解决方案

多亏了Raymond Wong,解决方案非常有效。

只是想进一步扩展它以使其可以使用应用程序设置进行配置

"AppSettings":{
"MaxInstances":2
}

然后在注册后台服务时

var limit = appSettings.MaxInstances;
for (int i = 0; i < limit ; i++)
{
services.AddSingleton<IHostedService, Worker>();
}

因此,我们可以从 Azure 配置中控制实例数。

最新更新