dotnet 控制台应用程序,使用通用主机 HostedService,Windows Task Scheduler 保持在 运行 状态

dotnet console app, using generic host, HostedService, Windows Task Scheduler stays in running state

试图弄清楚为什么我的控制台应用程序不会停止 运行。

在 dotnet 核心应用程序主要方法中使用以下方法:

await new HostBuilder().
...
 .ConfigureServices((hostContext, services) =>
  {     
     services.AddHostedService<MyHostedService>(); 
  })
 .UseConsoleLifetime()
 .Build()
 .RunAsync();

使用以下设置从 Windows 任务计划程序发布和计划该任务有效:

到目前为止一切都很好。所有代码都正确执行。但是,任务保持 运行,过程永远不会结束。 (即使在任务计划程序的 UI 上按刷新后也没有)

这是预期的吗?如果没有,我如何让进程终止?

如果预期的话,在刚刚启动、运行和停止的预定控制台应用程序中使用通用主机/托管服务是否仍然有意义?

答案基于Microsoft.Extensions.Hosting 2.2.0

由于您对 Generic Host:

的使用,此行为是预料之中的

它会保持 运行ning 直到关闭或处置,并且您没有适当的关闭机制。我假设您希望 Generic HostIHostedService.StartAsync(CancellationToken) 完成 MyHostedService 运行 后关闭。事实并非如此,因为可能还有其他 IHostedService 实现按顺序注册和执行, and/or long 运行ning BackgroundService returns 控制其 ExecuteAsync(CancellationToken) 未同步完成以允许其他服务并行 运行。

在您的 MyHostedService 任务完成后通过 RunAsync, you should constructor-inject the IApplicationLifetime into your MyHostedService and call StopApplication 连接主机时 运行 完成后优雅地停止您的应用程序。

internal class MyHostedService : IHostedService
{
    private readonly IApplicationLifetime _appLifetime;

    public MyHostedService(IApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await Task.Delay(1000); //your scheduled work

        _appLifetime.StopApplication();
    }

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

此外,可以通过预先注册为默认生命周期实现的 AppDomain.CurrentDomain.ProcessExit or Console.CancelKeyPress, both events are subscribed to by the ConsoleLifetime 停止应用程序。

您可以在 docs 中阅读有关生命周期管理的更多信息。

Microsoft.Extensions.Hosting 3.0.0 - 目前处于预览阶段 - 标记为 IApplicationLifetime 已过时并建议使用 IHostApplicationLifetime 代替