3.0ソース・ホスト(II)の.NETコア深い理解

 

EDITORIAL

彼は正式に復元された後、スネア996からの公式で、技術的なブログのほぼ月を停止しました。また、ビューのソースポイントから延びるホストについてのいくつかの技術的なポイントでは、本明細書に.NETのコア3.0を議論し、ロングランプログラムが作成し、保護者に焦点を当てています。

ホストについて、私たちは、プログラムの起動と停止を考える可能性が最も高い、非常に重要な機能を隠しているのホストの初期化で、我々は必見を必要とし、初期化する必要があり、すべてのリソースが完了したプログラムは、当然のことながら、この記事をプロセスを開始します主なコンテンツは、以前に疲れていない初期化されているホスト。もちろん、ホストのサブスクリプションのライフサイクルイベントを開くために、.NETのコア3.0プログラムは、より良い守ると管理は、ホストサービスのカスタムオブジェクトを含む、もちろん、開発者に開始しました。

注意:このコードは、.NETのコア3.0 Preview9に基づいています

HOST2

ロングファイル名を指定して実行プログラムを作成するために、.NETのコア3.0

IHostとIHostBuilder

私たちは長いファイル名を指定して実行プログラムを作成すると、最初のスタートを集中し、プログラムを停止し、.NETのコア3.0はIHost、インターフェースがMicrosoft.Extensions.Hostingクラスライブラリに配置され、この目的のためのインタフェースを提供し、次のように、そのソースコードは次のとおりです。

   1:   /// <要約>
   2:   ///プログラムの抽象化。
   3:   /// </要約>
   4:   パブリック インタフェース IHost:IDisposableを
   5:   {
   6:       /// <要約>
   7:      /// The programs configured services.
   8:      /// </summary>
   9:      IServiceProvider Services { get; }
  10:   
  11:      /// <summary>
  12:      /// Start the program.
  13:      /// </summary>
  14:      /// <param name="cancellationToken">Used to abort program start.</param>
  15:      /// <returns>A <see cref="Task"/> that will be completed when the <see cref="IHost"/> starts.</returns>
  16:      Task StartAsync(CancellationToken cancellationToken = default);
  17:   
  18:      /// <summary>
  19:      /// Attempts to gracefully stop the program.
  20:      /// </summary>
  21:      /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param>
  22:      /// <returns>A <see cref="Task"/> that will be completed when the <see cref="IHost"/> stops.</returns>
  23:      Task StopAsync(CancellationToken cancellationToken = default);
  24:  }

该接口含有一个只读属性:IServiceProvider Services { get; },通过该属性,我们可以拿到所有Host初始化时所注入的对象信息。

IHostBuilder接口所承担的核心功能就是程序的初始化,通过:IHost Build()来完成,当然只需要运行一次即可。其初始化内容一般包括以下几个功能:

HOST3

另外需要说明的是,以上功能的初始化,是通过IHostBuilder提供的接口获取用户输入的信息后,通过调用Build()方法来完成初始化。以下为IHostBuilder的部分源代码:

   1:  /// <summary>
   2:  /// Set up the configuration for the builder itself. This will be used to initialize the <see cref="IHostEnvironment"/>
   3:  /// for use later in the build process. This can be called multiple times and the results will be additive.
   4:  /// </summary>
   5:  /// <param name="configureDelegate">The delegate for configuring the <see cref="IConfigurationBuilder"/> that will be used
   6:  /// to construct the <see cref="IConfiguration"/> for the host.</param>
   7:  /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
   8:  public IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate)
   9:  {
  10:      _configureHostConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate)));
  11:      return this;
  12:  }
  13:   
  14:  /// <summary>
  15:  /// Adds services to the container. This can be called multiple times and the results will be additive.
  16:  /// </summary>
  17:  /// <param name="configureDelegate">The delegate for configuring the <see cref="IConfigurationBuilder"/> that will be used
  18:  /// to construct the <see cref="IConfiguration"/> for the host.</param>
  19:  /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
  20:  public IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
  21:  {
  22:      _configureServicesActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate)));
  23:      return this;
  24:  }
  25:   
  26:  /// <summary>
  27:  /// Overrides the factory used to create the service provider.
  28:  /// </summary>
  29:  /// <typeparam name="TContainerBuilder">The type of the builder to create.</typeparam>
  30:  /// <param name="factory">A factory used for creating service providers.</param>
  31:  /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
  32:  public IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory)
  33:  {
  34:      _serviceProviderFactory = new ServiceFactoryAdapter<TContainerBuilder>(factory ?? throw new ArgumentNullException(nameof(factory)));
  35:      return this;
  36:  }
  37:   
  38:  /// <summary>
  39:  /// Enables configuring the instantiated dependency container. This can be called multiple times and
  40:  /// the results will be additive.
  41:  /// </summary>
  42:  /// <typeparam name="TContainerBuilder">The type of the builder to create.</typeparam>
  43:  /// <param name="configureDelegate">The delegate for configuring the <see cref="IConfigurationBuilder"/> that will be used
  44:  /// to construct the <see cref="IConfiguration"/> for the host.</param>
  45:  /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
  46:  public IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate)
  47:  {
  48:      _configureContainerActions.Add(new ConfigureContainerAdapter<TContainerBuilder>(configureDelegate
  49:          ?? throw new ArgumentNullException(nameof(configureDelegate))));
  50:      return this;
  51:  }

IHostService

文章开头有说过自定义Host Service对象,那么我们如何自定义呢,其实很简单只需要实现IHostService,并在ConfigureServices中调用services.AddHostedService<MyServiceA>()即可,以下是IHostService的源码:

   1:  /// <summary>
   2:  /// Defines methods for objects that are managed by the host.
   3:  /// </summary>
   4:  public interface IHostedService
   5:  {
   6:      /// <summary>
   7:      /// Triggered when the application host is ready to start the service.
   8:      /// </summary>
   9:      /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
  10:      Task StartAsync(CancellationToken cancellationToken);
  11:   
  12:      /// <summary>
  13:      /// Triggered when the application host is performing a graceful shutdown.
  14:      /// </summary>
  15:      /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
  16:      Task StopAsync(CancellationToken cancellationToken);
  17:  }

根据源码我们可以知道,该接口只有两个方法,即代码程序开始与停止的方法。具体的实现可以参考如下:

   1:  public class MyServiceA : IHostedService, IDisposable
   2:  {
   3:      private bool _stopping;
   4:      private Task _backgroundTask;
   5:   
   6:      public MyServiceA(ILoggerFactory loggerFactory)
   7:      {
   8:          Logger = loggerFactory.CreateLogger<MyServiceB>();
   9:      }
  10:   
  11:      public ILogger Logger { get; }
  12:   
  13:      public Task StartAsync(CancellationToken cancellationToken)
  14:      {
  15:          Logger.LogInformation("MyServiceB is starting.");
  16:          _backgroundTask = BackgroundTask();
  17:          return Task.CompletedTask;
  18:      }
  19:   
  20:      private async Task BackgroundTask()
  21:      {
  22:          while (!_stopping)
  23:          {
  24:              await Task.Delay(TimeSpan.FromSeconds(7));
  25:              Logger.LogInformation("MyServiceB is doing background work.");
  26:          }
  27:   
  28:          Logger.LogInformation("MyServiceB background task is stopping.");
  29:      }
  30:   
  31:      public async Task StopAsync(CancellationToken cancellationToken)
  32:      {
  33:          Logger.LogInformation("MyServiceB is stopping.");
  34:          _stopping = true;
  35:          if (_backgroundTask != null)
  36:          {
  37:              // TODO: cancellation
  38:              await _backgroundTask;
  39:          }
  40:      }
  41:   
  42:      public void Dispose()
  43:      {
  44:          Logger.LogInformation("MyServiceB is disposing.");
  45:      }
  46:  }

IHostService是我们自定义Host管理对象的入口,所有需要压入到Host托管的对象都必须要实现此接口。

Host生命周期的管理

该接口提供了一种我们可以在程序运行期间进行管理的功能,如程序的启动与停止事件的订阅,关于Host生命周期的管理,主要由IHostApplicationLifetime和IHostLifetime这两个接口来完成。

以下是IHostApplicationLifetime的源码​

   1:  public interface IHostApplicationLifetime
   2:  {
   3:      /// <summary>
   4:      /// Triggered when the application host has fully started.
   5:      /// </summary>
   6:      CancellationToken ApplicationStarted { get; }
   7:   
   8:      /// <summary>
   9:      /// Triggered when the application host is performing a graceful shutdown.
  10:      /// Shutdown will block until this event completes.
  11:      /// </summary>
  12:      CancellationToken ApplicationStopping { get; }
  13:   
  14:      /// <summary>
  15:      /// Triggered when the application host is performing a graceful shutdown.
  16:      /// Shutdown will block until this event completes.
  17:      /// </summary>
  18:      CancellationToken ApplicationStopped { get; }
  19:   
  20:      /// <summary>
  21:      /// Requests termination of the current application.
  22:      /// </summary>
  23:      void StopApplication();
  24:  }

IHostLifetime源码如下:

   1:  public interface IHostLifetime
   2:  {
   3:      /// <summary>
   4:      /// Called at the start of <see cref="IHost.StartAsync(CancellationToken)"/> which will wait until it's complete before
   5:      /// continuing. This can be used to delay startup until signaled by an external event.
   6:      /// </summary>
   7:      /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param>
   8:      /// <returns>A <see cref="Task"/>.</returns>
   9:      Task WaitForStartAsync(CancellationToken cancellationToken);
  10:   
  11:      /// <summary>
  12:      /// Called from <see cref="IHost.StopAsync(CancellationToken)"/> to indicate that the host is stopping and it's time to shut down.
  13:      /// </summary>
  14:      /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param>
  15:      /// <returns>A <see cref="Task"/>.</returns>
  16:      Task StopAsync(CancellationToken cancellationToken);
  17:  }

具体的使用可以参考如下代码:

   1:  public class MyLifetime : IHostLifetime, IDisposable
   2:  {
   3:      .........
   4:   
   5:      private IHostApplicationLifetime ApplicationLifetime { get; }
   6:   
   7:      public ConsoleLifetime(IHostApplicationLifetime applicationLifetime)
   8:      {
   9:          ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));
  10:      }
  11:   
  12:      public Task WaitForStartAsync(CancellationToken cancellationToken)
  13:      {
  14:          _applicationStartedRegistration = ApplicationLifetime.ApplicationStarted.Register(state =>
  15:          {
  16:              ((ConsoleLifetime)state).OnApplicationStarted();
  17:          },
  18:          this);
  19:          _applicationStoppingRegistration = ApplicationLifetime.ApplicationStopping.Register(state =>
  20:          {
  21:              ((ConsoleLifetime)state).OnApplicationStopping();
  22:          },
  23:          this);
  24:   
  25:          .......
  26:   
  27:          return Task.CompletedTask;
  28:      }
  29:   
  30:      private void OnApplicationStarted()
  31:      {
  32:          Logger.LogInformation("Application started. Press Ctrl+C to shut down.");
  33:          Logger.LogInformation("Hosting environment: {envName}", Environment.EnvironmentName);
  34:          Logger.LogInformation("Content root path: {contentRoot}", Environment.ContentRootPath);
  35:      }
  36:   
  37:       プライベート 無効 OnApplicationStopping()
  38:       {
  39:           Logger.LogInformation("アプリケーションがシャットダウンしています...");
  40:       }
  41:   
  42:       ........
  43:   }

概要

これまでのところ、我々はロングランプログラムは、いくつかのポイントに焦点を当てる必要性を作成したことを知って、それぞれ、IHostServiceは、継承されたプログラムのライフサイクルタイムと初期化プロセスのホストに加入します。相対的に言って、このコンテンツは比較的簡単ですが、開発プロセスは、まだ私たちが実際に必要とするなど、タイミング機構タスク、情報へのアクセス、およびパフォーマンスの最適化の手順、など多くの問題を、遭遇しますさらに要約を向上させます。

おすすめ

転載: www.cnblogs.com/edison0621/p/11520497.html