点网核心 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 配置中控制实例数。