dot net core 3.0 worker 服务模板如下图所示:
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>();
});
}
Run Code Online (Sandbox Code Playgroud)
“Worker”类派生自 BackgroundService。它每 1000 毫秒循环一次将日志写入控制台。
我的问题:
我可以同时运行多个“工人”吗?(我知道我可以创建另一个类“Worker2”。但是我可以运行同一个类“Worker”的两个副本吗?)
如果是,我如何配置两个具有不同配置或参数的“工人”,例如,两个具有不同循环间隔的工人?(因为“Worker”类的实例是由DI框架创建的。我不知道如何将不同的配置/参数传递给“Worker”的两个不同实例)
Ed *_*ald 15
You can have a "parent" worker that launches the "real" workers like this...
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());
}
}
Run Code Online (Sandbox Code Playgroud)
Then...
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);
}
}
Run Code Online (Sandbox Code Playgroud)
_config gets populated from appSettings.json and passed in to the constructor of the Worker like this...
var cfg = hostContext.Configuration.GetSection(nameof(WorkerConfig)).Get<WorkerConfig>();
services.AddSingleton(cfg);
services.AddHostedService<Worker>();
Run Code Online (Sandbox Code Playgroud)
and the appSettings...
{
"WorkerConfig": {
"LoopIntervals": [ 1000, 2000, 3000 ]
}
}
Run Code Online (Sandbox Code Playgroud)
Ray*_*ong 11
“AddHostedService”不接受同一个类注册两次的原因:
我查了“AddHostedService”的github源码,发现是这样实现的:
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());
Run Code Online (Sandbox Code Playgroud)
根据“TryAddEnumerable”方法的 Microsoft 文档,仅当集合不包含相同服务和实现类型的其他注册时才添加服务。这就是为什么我不能运行“Worker”的两个副本的原因。(故意使用“TryAddEnumerable”来避免为同一服务创建多个实例。参考:https : //github.com/aspnet/Extensions/issues/1078)
解决方案:
所以我可以直接使用“AddSingleton”添加两个工人......
services.AddSingleton<IHostedService, Worker>();
services.AddSingleton<IHostedService, Worker>();
Run Code Online (Sandbox Code Playgroud)
有用。
将参数传递给服务构造函数:
然后,我通过为循环间隔添加第二个参数来修改 Worker 类构造函数。最后,我在注册服务时使用实现工厂如下
services.AddSingleton<IHostedService>(sp => new Worker(sp.GetService<ILogger<Worker>>(), 1000));
services.AddSingleton<IHostedService>(sp => new Worker(sp.GetService<ILogger<Worker>>(), 2000));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6372 次 |
| 最近记录: |