如何在 .net core 3.0 中执行一次工作服务?

3
我是一名中文翻译助手,以下是翻译结果:

我正在使用.NET Core 3.0中的服务工作者模板。 我想要做的是,只有当我的参数“ExecuteOnce”在appsettings.json中设置为true时,才执行此服务。

Program.cs:

public class Program
    {
        public static IServiceProvider Services { get; set; }
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostContext, config) =>
                {
                    if (hostContext.HostingEnvironment.IsProduction())
                        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
                    else
                        config.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true);

                    config.SetBasePath(Directory.GetCurrentDirectory());
                })
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                });
        public static void Main(string[] args)
        {
                CreateHostBuilder(args).Build().Run();
        }
    }

Worker.cs :

public class Worker : BackgroundService
    {
        private readonly IConfiguration _configuration;
        public Worker(ILogger<Worker> logger, IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public override Task StartAsync(CancellationToken cancellationToken)
        {
            return base.StartAsync(cancellationToken); ;
        }

        public override Task StopAsync(CancellationToken cancellationToken)
        {
            return base.StopAsync(cancellationToken);
        }

        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                // Bit of logic here...

                if (_configuration.GetValue<bool>("TaskConfig:ExecuteOnce"))
                    // TODO HERE : stop this service
                else
                    await Task.Delay(_configuration.GetValue<int>("TaskConfig:TaskDelayMs"), new CancellationToken());
            }
        }
    }

我尝试过:

  • 等待Task.TaskCompleted
  • 中断循环
  • 调用StopAsync()

但每次都遇到了一些限制,正确的实现方式是什么?


如果我理解你的意思正确的话,你只是希望服务运行一次,执行某些操作,然后退出,如果ExecuteOnce为真。这不是一个正确的服务设计。服务应该长时间运行,并与其他系统/应用程序/服务进行交互。你所需要做的可以通过一个简单的应用程序来实现,你可以为其安排单次执行。 - Nick
@Nick,我不认为这一定是无效的。例如,你可能有一个应用程序,它可以自己进行调度,或者可以通过外部调度程序运行。与其拥有两个代码库,你可能希望按照OP所问的方式来实现它。 - RB.
@RB,一个服务不应该就这样退出。一个服务应该由SCM控制。如果一个服务自己退出,通常被视为错误。 - Nick
@Nick 不一定 - 考虑一种情况,其中SCM不是服务控制管理器,而是Kubernetes或类似的东西。也许你想要根据某个外部事件(如GitHub提交或其他事件)启动服务,然后运行一次后关闭。我的意思是,我同意你这样认为是不寻常的,但我不认为说它是错误的是公平的。 - RB.
@RB,你还是没有理解一个服务的本质在于它的生命周期是由外部控制的这一点。 - Nick
1个回答

11
使用 IHostApplicationLifetime 接口,你可以让你的应用程序自行关闭。
public class Worker : BackgroundService
{
    private readonly IHostApplicationLifetime _hostLifetime;

    public Worker(IHostApplicationLifetime hostLifetime) 
    {
        _hostLifetime = hostLifetime;    
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (true)
        {
            DoWork();
            if (RunOnlyOnce())
            {
                _hostLifetime.StopApplication();
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接