在 .NET 核心中并行运行的多个辅助角色



我在 .NET Core 中创建了一个辅助角色服务项目,目的是让 3 个独立的辅助角色。所有这 3 个工作线程都应并行运行并独立于其他工作线程。这个辅助角色服务作为一个整体将作为 Windows 服务运行。

在主计划中.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(( 开始工作之前做某事。

请告知他们如何独立工作,即:每个工人不应该等待其他工人,而应该独立运行。

当我执行项目时,我遇到了一些问题,例如,当 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);
}
});

可悲的是,在.net Core中,您只能初始化1个HostedService,这意味着只有第一个inyected将在后台运行。一个可行的解决方案是创建一个 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));
}
}

最新更新