What is generic Host?
This is a new host added to ASP. 2.1 Version of ASP. NET core, there are two available host.
- Web host – host for hosting web programs is the common webhost that we are familiar with in the MAI function of an ASP. NET core application, created with Createwebhostbuilder.
- Generic Host (Available in ASP. NET Core 2.1) – for hosting non-Web apps (for example, apps that run background tasks). In a future release, a generic host will be available for hosting any type of app, including Web apps. The common host will eventually replace the WEB host, which is probably the reason this type of host is called a universal host, in this blog, we will combine the source code to discuss how the common host works.
Why use a generic host?
The universal host allows me to simplify the creation of console applications (personal insights) with the idea of writing ASP. NET core (e.g., control inversion, Dependency injection, IOC container), host responsible for program initiation and life cycle management, This is useful for applications that do not handle HTTP requests (Web applications that handle HTTP requests, hosted by web host), and the goal of the universal host is to detach the HTTP pipeline from the web host, making the same thing as the ASP for the other. Net Core. Core program.
Demo download
Before starting to follow my analysis of the universal host, you can download this official demo on GitHub.
github.com/aspnet/docs/tree/master/aspnetcore/fundamentals/host/generic-host/samples/
If you feel that downloading a whole is slow, can be downloaded from my GitHub repository, there is no other content, domestic github is slower, if you download from the official that warehouse may take a long time or even fail.
Github.com/liuzhenyulive/generic-host-demo
Generic host vs. Web Host
First, we open the download of the official demo, into the main function.
As you can see, this is simply a lite ASP. NET core application, and for all the methods that appear in this main function, you are familiar with the ASP. NET core Web application, so I made a comparison with the webhost of ASP. To help you find the feeling.
Universal Host |
Web Host |
New Hostbuilder () |
Webhost.createdefaultbuilder (args) |
Configureappconfiguration (Used to configure configuration) |
Webhost also has this method, but everyone by default may not be called. |
Configureservices (for configuring service, that is, dependency injection) |
Webhost actually has a configureservices method that can be called. However, we rarely use this, usually in the startup Configureservices method for dependency injection. |
Configurelogging (Required configuration for this application, not required) |
Webhost is still there! |
Builder. Runconsoleasync () The Runconsoleasync is actually a hostbuilder. Builder then run |
Createwebhostbuilder (args). Build (). Run (); This is the build () in the main function. Run (); |
No no no no no |
The Configure () method in startup ASP. NET core configuration for HTTP request pipeline in this method |
In contrast, I have done the following summary!
- There is a WEB host for the Universal host (Generic hosts).
- The HTTP pipeline of Web host, or Startup.configure (), is not in the generic host.
This should be the beginning: The goal of the Universal host is to detach the HTTP pipeline from the web host, making the same set of ASP. Net core programs available to other.
How do I use it? Interpretation of the Run function
I think we need to know how to use it, so let's start by knowing what the host is doing inside the Run method.
So we go deep into the source, all the way f12!
Builder. Runconsoleasync (); =>hostbuilder.useconsolelifetime (). Build (). RunAsync (cancellationtoken); = = await host. Startasync (token);
Finally found, the most critical here.
Publicpublic 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();
}
}
Know that everyone likes yellow color, so I use yellow to put the most critical code out, then what is the meaning of the code?
This._hostedservices = this. Services.getservice<ienumerable<ihostedservice>> ();
This line means that all services that implement the Ihostedservice are removed from the container.
This means that after we have implemented the Ihostedservice, we need to register the service with the IOC container.
foreach (Ihostedservice hostedservice in this._hostedservices)
Await Hostedservice.startasync (CancellationToken). Configureawait (FALSE);
Executes the Startasync method for each service.
So, do you know how to use it?
The steps I summarize are as follows:
- Customize a service that inherits the Ihostedservice interface.
- Implement the Ihostedservice Startasync method and put the tasks that need to be performed into this method.
- Register the service in the IOC container (servicecollection).
The custom task runs for steps 1 and 2, and the corresponding code is as follows:
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, a timed task is defined, with a timed task that executes the DoWork method every five seconds.
In the DoWork method, the Logger logs a section of content.
Because in the main method, the log is configured as follows.
So, once the log is logged, the content is 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 generic 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 to use Log to output the content in the console)
Await builder.RunConsoleAsync(); //Run the generic host in the console application
}
The yellow section registers the Printtexttoconsoleservice that implement the Ihostedservice interface in the container.
F5 Run
As you can see, in the console, there is a content output every five seconds, which means that the DoWork method has not been executed for five seconds, indicating that Printtexttoconsoleservice's Startasync was successfully invoked.
I hope this article will help you understand the common host can help, if the. Net Core source code analysis, the trend of new technology interested
Welcome to follow me
Not regularly launched practical work, thank you!
Reference documents