我已经在.NET Core中创建了一个工人服务项目,其目的是让3位独立工人参与。所有这三名工人应并行运行,并且独立于其他工人。整个工作服务将作为Windows服务运行。
在主Program.cs中,我注册了3个工人,如下所示:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
services.AddHostedService<WorkerA>();
services.AddHostedService<WorkerB>();
services.AddHostedService<WorkerC>();
});
}
每个工作人员代码如下,完成其预期的工作:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
WorkerA_DoWork();
await Task.Delay(6000, stoppingToken);
}
}
问题陈述:当我执行项目时,遇到的问题很少,例如,当WorkerA()没有任何进程要运行时,WorkerB()(或)WorkerC()不会开始工作。我认为基本上是在等待WorkerA()做一些事情之后,WorkerB()或WorkerC()才能开始工作。
[请告知他们如何独立工作,即:每个工人都不应等待其他工人,而应独立运行。
不幸的是,在.net Core中,您只能初始化1 HostedService,这意味着只有第一个被集成的主机会在后台运行。一个可行的解决方案是创建一个HostedService包装器,该包装器将初始化您的类:
public class Orchestrator: IHostedService
{
private readonly WorkerA _workerA;
private readonly WorkerB _workerB;
public Orchestrator(WorkerA workerA, WorkerB workerB)
{
_workerA = workerA;
_workerB = workerB;
}
#endregion
public Task StartAsync(CancellationToken cancellationToken)
{
Task.Run(async () => await _workerA.StartAsync(cancellationToken));
Task.Run(async () => await _workerB.StartAsync(cancellationToken));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.WhenAll(StartAsync(cancellationToken));
}
}
[执行项目时,我遇到的问题很少,例如,当WorkerA()没有任何进程要运行时,WorkerB()(或)WorkerC()不会开始工作。我认为基本上是在等待WorkerA()做一些事情之后,WorkerB()或WorkerC()才能开始工作。
。NET Core允许任何数量的托管服务;但是,它开始串行执行它们。所以这段代码的问题:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
WorkerA_DoWork();
await Task.Delay(6000, stoppingToken);
}
}
是WorkerA_DoWork
是同步的。也就是说,它正在同步等待工作完成。
解决方案可以是两件事之一。使“获取下一个工作项”方法异步:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await WorkerA_DoWorkAsync();
await Task.Delay(6000, stoppingToken);
}
}
或将整个ExecuteAsync
包装在Task.Run
中:
protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.Run(async () =>
{
while (!stoppingToken.IsCancellationRequested)
{
WorkerA_DoWork();
await Task.Delay(6000, stoppingToken);
}
});