IHostedService
这个接口只包含两个成员方法:
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
Host中可以包含多个IHostedService服务实例。当然,如果是Web应用其中一个就是WebHost。Host起来之后,会依次启动所有添加的这些IHostedService服务。
下面我们给一个例子,如何在Web服务之外注入自己的一个服务程序。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
using System.Diagnostics;
namespace aspnetapp
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
public class Worker : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
Debug.WriteLine("Start");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
Debug.WriteLine("End");
return Task.CompletedTask;
}
}
}
上面的例子中,Worker就是我们自己定义的一个服务程序。整个系统运行起来后,它会自动调用Worker.StartAsync()方法。
此外,如果我们想控制我们自己的服务程序的生命周期,那么可以使用IHostApplicationLifetime,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
using System.Diagnostics;
namespace aspnetapp
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
public class Worker : IHostedService
{
private readonly ILogger _logger;
private readonly IHostApplicationLifetime _appLifetime;
public Worker(ILogger<Worker> logger, IHostApplicationLifetime appLifetime)
{
_logger = logger;
_appLifetime = appLifetime;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_appLifetime.ApplicationStarted.Register(OnStarted);
_appLifetime.ApplicationStopping.Register(OnStoping);
_appLifetime.ApplicationStopped.Register(OnStopped);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private void OnStarted()
{
_logger.LogInformation("OnStarted has been called.");
}
private void OnStoping()
{
_logger.LogInformation("OnStoping has been called.");
}
private void OnStopped()
{
_logger.LogInformation("OnStopped has been called.");
}
}
}
Asp.net Core框架内部会自己注入一个IHostApplicationLifetime实例,它是Singleton的,也就是它是一个单一实例。所有注入的主机都用这一个IHostApplicationLifetime实例进行生命周期管理,那为什么单个生命周期管理实例就可以管多个主机的生命周期呢?这是由于Cancellationtoken对象的Register()方法是可以调用多次,即可以注册多次回调的委托方法的。IHostApplicationLifetime实例是在HostBuilder类中注入的(下面是截取的代码片段):
private void CreateServiceProvider()
{
var services = new ServiceCollection();
services.AddSingleton(_hostingEnvironment);
services.AddSingleton(_hostBuilderContext);
services.AddSingleton(_appConfiguration);
services.AddSingleton<IApplicationLifetime, ApplicationLifetime>();
services.AddSingleton<IHostLifetime, ConsoleLifetime>();
services.AddSingleton<IHost, Host>();
services.AddOptions();
services.AddLogging();
// ....
// ....
上面这段是找到的官方源码,应该不是微软最新的。IApplicationLifetime其实就是现在的IHostApplicationLifetime。IApplicationLifetime已经做旧,已经被IHostApplicationLifetime替代,两个接口内部的定义完全一样。但是就是找不到IHostApplicationLifetime官方源码,只是从别人的博客里看到说两个接口是一样的。