.NET 8 中的 IHostedLifecycleService 原创 WeihanLi amazingdotnet 2023-08-13 23:58

Intro

.NET 8 中引入了一个 IHostedLifecycleService 作为 IHostedService 的补充,我们在服务开始、结束之前和之后添加自定义的处理逻辑。.

New API

/// <summary>
/// Defines methods that are run before or after
/// <see cref="IHostedService.StartAsync(CancellationToken)"/> and
/// <see cref="IHostedService.StopAsync(CancellationToken)"/>.
/// </summary>
public interface IHostedLifecycleService : IHostedService
{
    /// <summary>
    /// Triggered before <see cref="IHostedService.StartAsync(CancellationToken)"/>.
    /// </summary>
    /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
    /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
    Task StartingAsync(CancellationToken cancellationToken);

    /// <summary>
    /// Triggered after <see cref="IHostedService.StartAsync(CancellationToken)"/>.
    /// </summary>
    /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
    /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
    Task StartedAsync(CancellationToken cancellationToken);

    /// <summary>
    /// Triggered before <see cref="IHostedService.StopAsync(CancellationToken)"/>.
    /// </summary>
    /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
    /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
    Task StoppingAsync(CancellationToken cancellationToken);

    /// <summary>
    /// Triggered after <see cref="IHostedService.StopAsync(CancellationToken)"/>.
    /// </summary>
    /// <param name="cancellationToken">Indicates that the stop process has been aborted.</param>
    /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
    Task StoppedAsync(CancellationToken cancellationToken);
}

Sample

来看一个简单示例,使用的时候也很简单,和 IHostedService 一样,参考下面的示例:

var hostBuilder = Host.CreateApplicationBuilder();
hostBuilder.Services.AddHostedService<MyHostedLifecycleService>();
var host = hostBuilder.Build();
await host.RunAsync();


file sealed class MyHostedLifecycleService : IHostedLifecycleService
{
    public Task StartAsync(CancellationToken cancellationToken) => ReportStatus();

    public Task StopAsync(CancellationToken cancellationToken) => ReportStatus();

    public Task StartedAsync(CancellationToken cancellationToken) => ReportStatus();

    public Task StartingAsync(CancellationToken cancellationToken) => ReportStatus();

    public Task StoppedAsync(CancellationToken cancellationToken) => ReportStatus();

    public Task StoppingAsync(CancellationToken cancellationToken) => ReportStatus();
    
    private static Task ReportStatus([CallerMemberName] string? methodName = default)
    {
        Console.WriteLine($"{nameof(MyHostedLifecycleService)} {methodName}");
        return Task.CompletedTask;
    }
}

输出结果如下:

.NET 8 中的 IHostedLifecycleService 原创 WeihanLi amazingdotnet 2023-08-13 23:58

output

HostApplicationLifetime

除了新增的这个 IHostedLifecycleService API 在之前的版本中我们可以借助 IHostApplicationLifetime 来注册一些简单的逻辑,示例如下:

var hostAppLifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();
hostAppLifetime.ApplicationStarted.Register(() => Console.WriteLine($"{nameof(IHostApplicationLifetime)} {nameof(hostAppLifetime.ApplicationStarted)}"));
hostAppLifetime.ApplicationStopping.Register(() => Console.WriteLine($"{nameof(IHostApplicationLifetime)} {nameof(hostAppLifetime.ApplicationStopping)}"));
hostAppLifetime.ApplicationStopped.Register(() => Console.WriteLine($"{nameof(IHostApplicationLifetime)} {nameof(hostAppLifetime.ApplicationStopped)}"));

那这些注册和 IHostedLifecycleService 里的注册执行顺序又是什么样的呢,我们更新下示例再执行一下看看,输出结果如下:

.NET 8 中的 IHostedLifecycleService 原创 WeihanLi amazingdotnet 2023-08-13 23:58

sequence

对于启动的顺序:

  • HostedLifecycleService StartingAsync
  • HostedLifecycleService StartAsync
  • HostedLifecycleService StartedAsync
  • IHostApplicationLifetime ApplicationStarted

对于停止的顺序:

  • IHostApplicationLifetime ApplicationStopping
  • HostedLifecycleService StoppingAsync
  • HostedLifecycleService StopAsync
  • HostedLifecycleService StoppedAsync
  • IHostApplicationLifetime ApplicationStopped

More

实现的细节可以参考这个 PR:https://github.com/dotnet/runtime/pull/87335

针对有些需要在服务启动前或者是需要预热的一些逻辑可以考虑基于 IHostedLifecycleService 来实现了,之前的一些基于 IHostApplicationLifetime 注册的一些异步操作的逻辑也可以考虑迁移到 IHostedLifecycleService 来