运行一个长任务IHosted服务同时可以手动开启关闭

Running a long task IHosted service at the same time and can manually turned on and off

您好,我在使用 IHostedService 为我的后台服务 运行 设置一个长期任务时遇到了问题,起初它确实工作正常,但在长期 运行 后台服务突然停止了线程退出代码:

The thread 10824 has exited with code 0 (0x0).
The thread 12340 has exited with code 0 (0x0).
The thread 9324 has exited with code 0 (0x0).
The thread 11168 has exited with code 0 (0x0).
The thread 11616 has exited with code 0 (0x0).
The thread 9792 has exited with code 0 (0x0).

我将我的后台服务注册为

//Register Background 
serviceCollection.AddSingleton<CoinPairBackgroundService>
serviceCollection.AddSingleton<SaveFakePersonBackgroundService>();
serviceCollection.AddSingleton<LeaderboardMinutesBackgroundService>();
serviceCollection.AddSingleton<LeaderboardHoursBackgroundService>();

serviceCollection.AddSingleton<IHostedService, CoinPairBackgroundService>();
serviceCollection.AddSingleton<IHostedService, SaveFakePersonBackgroundService>();
serviceCollection.AddSingleton<IHostedService, LeaderboardMinutesBackgroundService>();
serviceCollection.AddSingleton<IHostedService, LeaderboardHoursBackgroundService>();

因为将来我想使用

手动打开和关闭我的后台服务
IServiceProvider provider = _serviceProvider.GetService<MyBackgroundServiceHere>();
provider.StartAsync();
provider.StopAsync

这是我后台服务 StartAsync 中的代码

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogDebug("Leaderboard minute ranking updates is starting");
        Task.Run(async () =>
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                _logger.LogDebug("Leaderboard minute ranking updates  is dequeueing");
                await DequeueRandomCustomers();

                _logger.LogDebug("Leaderboard minute ranking updates  is enqueueing");
                await EnqueueRandomCustomers();

                _logger.LogDebug("Leaderboard minute ranking updates  thread is now sleeping");
                //sleep for 1 minute
                await Task.Delay(new TimeSpan(0, 0, 10));
            }
        });
        return Task.CompletedTask;
    }

如果注册我的后台服务有问题,我会感到困惑,因为我看到我的后台服务启动了,但在很长一段时间内 运行 它突然停止了,我已经摆脱了那些 Thread.Sleep()在我的后台服务中希望你能帮忙提前谢谢。

您可以在 appsettings.json 中设置服务配置,将其配置为 reloadOnChange: true,然后使用 IOptionsMonitor<> 访问当前值,而不是以这种奇怪的方式管理托管服务生命周期来自 appsettings.json。并将该设置用作托管服务 StartAsync 方法中启动任务的取消。并且您需要监听 IOptionsMonitor<>OnChange 事件以重新启动服务。

appsettings.json:

 "HostedService": {
    "RunService1": true
  }

这样注册选项:

public class HostedServiceConfig
{
     public bool RunService1 { get; set; }
}

services.Configure<HostedServiceConfig>(Configuration.GetSection("HostedService"));

然后创建HostedService1并在AddHostedService的帮助下注册:

 services.AddHostedService<HostedService1>();

下面是 StartAsync 的示例:

  public class HostedService1 : IHostedService
  {
        private readonly IOptionsMonitor<HostedServiceConfig> _options;
        private CancellationToken _cancellationToken;

        public HostedService1(IOptionsMonitor<HostedServiceConfig> options)
        {
            _options = options;

             // Or listen to changes and re-run all services from one place inside `Configure` method of `Startup`
            _options.OnChange(async o =>
            {
                if (o.RunService1)
                {
                    await StartAsync(_cancellationToken);
                }
            });
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            if(_cancellationToken == null) 
            {
                 _cancellationToken = cancellationToken;
            }

            Task.Run(async () =>
            {
                while (!_cancellationToken .IsCancellationRequested || !_options.CurrentValue.RunService1)
                {
                     ....
                }
            });

            return Task.CompletedTask;
        }

        ...
   }

如果 appSettings.json 内有任何变化,您 _options.CurrentValue.RunService1 将自动重新加载。