What is Generic Host?
This is the addition of a new Host in Asp. Net Core 2.1, and now in version 2.1, there are two available Hosts.
- Web Host –Host for hosting Web programs is a common WebHost created in the Mai function of an Asp. Net Core application using CreateWebHostBuilder.
- Generic Host (ASP.NET Core 2.1Version only) – suitable for hosting non Web applications (for example, running background tasks). In future releases, the universal host will be applicable to hosting any type of application, including Web applications. The universal host will eventually replace the Web host, which is probably the same type.The reason why hosts are called generic hosts is that in this blog, we’ll discuss how generic hosts work with source code.
Why use a universal host?
Generic hosts, which allow me to simplify the creation of console applications (personal opinions) by writing Asp. Net Core ideas (such as control inversion, dependency injection, IOC containers), are responsible for program startup and lifecycle management, which is useful for applications that don’t handle HTTP requestsThe order is very useful (Web applications handle HTTP requests, hosted by Web Host), and the goal of a generic host is to pull the HTTP pipeline out of Web Host so that the Asp. Net Core suite applies to other. Net Cores as well.E program.
Demodownload
Before you can follow me to analyze the universal host, you can download the official Demo at Github.
https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/host/generic-host/samples/
If you think downloading an entire one is slow, you can download it from my Github repository. There is no extra content. Domestic Github is slow. If you download it from the official repository, it may take a long time or even fail.
https://github.com/liuzhenyulive/Generic-Host-Demo
Generic Host Comparison with Web Host
First of all, you can download the official Demo and enter the Main function.
As you can see, this is a very compact version of the ASP. Net Core application, and you’re familiar with Asp. Net Core Web applications for all the methods that appear in this Main function, so I’m familiar with Asp. net core’s Web application.Host made a comparison to help you find the feeling.
General-purpose host | WebHost |
new HostBuilder() | WebHost.CreateDefaultBuilder(args) |
ConfigureAppConfiguration (Used to configure Configuration) |
WebHostThere is also this method, but you may not call it by default.![]() |
ConfigureServices (Used to configure Service, that is, dependency injection. |
WebHostIn fact, there are ConfigureServices methods that can be called.![]() But we rarely use this, and it’s usually placed in Startup’s ConfigureServices method for dependency injection. |
ConfigureLogging (Is the configuration, not necessary for this application. |
WebHostOr do you have it!![]() |
builder.RunConsoleAsync()![]() RunConsoleAsyncIn fact, it is for hostbuilder. BuilderThen Run |
CreateWebHostBuilder(args).Build().Run();
That is, Build ().Run () in the Main function. |
Nothing but nothing and nothing |
StartupThe Configure () method in Asp.net coreConfigure the Http request pipeline in this method. |
To sum up, I have done the following summary.
- Generic Host has some Web Host.
- Web HostHttp Pipeline, Startup.Configure (), does not exist in the general host.
This should prove the beginning:The goal of a generic host is to separate the HTTP pipeline from Web Host so that the Asp. Net Core suite can be applied to other. Net Core programs.
How to use it?
RunFunction interpretation
I think to know how to use it, we first need to know what’s going on inside Host’s Run method.
So we go deep into the source code, all the way to F12!
builder.RunConsoleAsync(); =>hostBuilder.UseConsoleLifetime().Build().RunAsync(cancellationToken);=> await host.StartAsync(token);
Finally found, the most critical here.
public async Task StartAsync(CancellationToken cancellationToken = default (CancellationToken)) { this._logger.Starting(); TaskCompletionSource<object> completionSource1 = new TaskCompletionSource<object>(); ref CancellationToken local = ref cancellationToken; TaskCompletionSource<object> completionSource2 = completionSource1; local.Register((Action<object>) (obj => ((TaskCompletionSource<object>) obj).TrySetCanceled()), (object) completionSource2); IHostLifetime hostLifetime1 = this._hostLifetime; TaskCompletionSource<object> completionSource3 = completionSource1; hostLifetime1.RegisterDelayStartCallback((Action<object>) (obj => ((TaskCompletionSource<object>) obj).TrySetResult((object) null)), (object) completionSource3); IHostLifetime hostLifetime2 = this._hostLifetime; ApplicationLifetime applicationLifetime = this._applicationLifetime; hostLifetime2.RegisterStopCallback((Action<object>) (obj => (obj as IApplicationLifetime)?.StopApplication()), (object) applicationLifetime); object task = await completionSource1.Task;
this._hostedServices = this.Services.GetService<IEnumerable<IHostedService>>(); foreach (IHostedService hostedService in this._hostedServices) await hostedService.StartAsync(cancellationToken).ConfigureAwait(false
); this._applicationLifetime?.NotifyStarted(); this._logger.Started(); }
Knowing that everyone likes the color Yellow, I’ve marked the most critical code with Yellow, so what does that mean?
this._hostedServices = this.Services.GetService<IEnumerable<IHostedService>>();
The meaning of this line is to remove all services that have implemented IHostedService from the container.
This means that after we have implemented the IHostedService, we need to register the Service into the IOC container.
foreach (IHostedService hostedService in this._hostedServices)
await hostedService.StartAsync(cancellationToken).ConfigureAwait(false);
Perform the StartAsync method for each service.
So, did you guess how to use it?
public class PrintTextToConsoleService : IHostedService, IDisposable { private readonly ILogger _logger; private readonly IOptions<AppConfig> _appConfig; private Timer _timer; public PrintTextToConsoleService(ILogger<PrintTextToConsoleService> logger, IOptions<AppConfig> appConfig) { _logger = logger; _appConfig = appConfig; } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Starting"); _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); return Task.CompletedTask; } private void DoWork(object state) { _logger.LogInformation($"Background work with text: {_appConfig.Value.TextToPrint}"); } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Stopping."); _timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public void Dispose() { _timer?.Dispose(); } }
As you can see, in StartAsync, you define a timed task that executes the DoWork method every five seconds with a timed task.
In the DoWork method, the log logger records a paragraph.
Because in the Main method, Log is configured as follows.
So once log is recorded, the content will be output in the console.
For step 3, the corresponding code is as follows
public static async Task Main(string[] args) { var builder = new HostBuilder() //Instantiate a universal host .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("appsettings.json", optional: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) //Configure Configuration .ConfigureServices((hostContext, services) => { services.AddOptions(); services.Configure<AppConfig>(hostContext.Configuration.GetSection("AppConfig")); services.AddSingleton
<IHostedService, PrintTextToConsoleService>
(); }) //Configure Service (dependency injection) .ConfigureLogging((hostingContext, logging) => { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); }); //Configure Log (in this project, use Log to output content in console). await builder.RunConsoleAsync(); //Running general host in console application }
The yellow part registers the PrintTextToConsoleService that implements the IHostedService interface into the container.
F5 Function
As you can see, every five seconds in the console, the content output indicates that the DoWork method is executed once every five seconds, and that StartAsync of the PrintTextToConsoleService is successfully invoked.
Hope this article can help you understand the general purpose host, if you are interested in. Net Core source analysis, new trend technology
Welcome to pay attention to me.
I will introduce practical work from time to time, thank you!
Reference
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.1