[ASP.NET Core 3 frame Disclosure] bearer service system [3]: General Design [Part I]

The previous example demonstrates the basic programming mode bearer services, then we rediscover service is hosted model in terms of design. In general, the service model is carried mainly by the three core shown below objects: a plurality of interface represents Build Service IHostedService is supported on the host interfaces represented by IHost, IHostBuilder interface represents an object by those IHost.

10-7

一, The Ho ste Foodservice

Bearer service will always be defined to implement the interface type IHostedService. As shown in the code segment below, the interface defines only two methods used to start and shut down their services. When an object is activated as IHost host, it will activate each frame using a dependency injection IHostedService service registration and start them by calling StartAsync method. When the service bearer when the application is closed, as a service host IHost objects will be closed, StopAsync method IHostedService each service object carried by it also will be invoked.

public interface IHostedService
{
    Task StartAsync(CancellationToken cancellationToken);
    Task StopAsync(CancellationToken cancellationToken);
}

Carrying system seamlessly integrates .NET Core dependency injection framework, the required bearer service during service dependent, and comprising bearer service itself it depends services are provided whereby the frame, the nature of the carrier service is registered corresponding IHostedService type or instance is registered to achieve dependency injection framework. Since most of the bearer service takes a long time to run until the application is closed, it is for the registration of bearer services generally use the Singleton life cycle model. Bearer registered bearer service system as defined in this AddHostedService <THostedService> extension method. Since this method by calling TryAddEnumerable extension method to register the service, so do not worry about duplicate registration service.

public static class ServiceCollectionHostedServiceExtensions
{
    public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services) where THostedService: class, IHostedService
    {
        services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());
        return services;
    }
}

Two, IHost

Bearer service represented by the interface is ultimately carried IHostedService represented by the interface IHost host on. In general, a service bearing applications throughout the life cycle will only create a IHost objects, we start and close applications on essentially startup and shutdown IHost object as the host . The following code fragment, IDisposable interface iHost interface is on, so when it is closed, its application calls Dispose method also make some additional work resource release. IHost Services IServiceProvider property returns the object interface as a dependency injection container, the subject service instance provides the required bearer service process, including the need to carry a IHostedService service. StopAsync methods and definitions StartAsync IHost interface completed startup and shutdown services for the host.

public interface IHost : IDisposable
{
    IServiceProvider Services { get; }
    Task StartAsync(CancellationToken cancellationToken = default);
    Task StopAsync(CancellationToken cancellationToken = default);
}

Third, the application life cycle

In the examples demonstrated earlier, after an object constructed IHost use HostBuilder object, we do not call its StartAsync method to start it, but another extension method called Run. Run method involves carrying application lifecycle management services, if you want to understand the nature of this method, you have to understand first named IHostApplicationLifetime interface. As the name suggests, IHostApplicationLifetime the interface reflects the life cycle of service hosting the application. The following code fragment, in addition to providing an interface to the three types of attributes CancellationToken application to detect when to turn on and off, but also provides a StopApplication to close the application.

public interface IHostApplicationLifetime
{
    CancellationToken ApplicationStarted { get; }
    CancellationToken ApplicationStopping { get; }
    CancellationToken ApplicationStopped { get; }

    void StopApplication();
}

ApplicationLifetime following types of IHostApplicationLifetime the default implementation of the interface. We can see the three properties that achieve the object CancellationToken returned from three CancellationTokenSource corresponding object, which correspond to three different methods (NotifyStarted, StopApplication and NotifyStopped). CancellationToken objects we can use IHostApplicationLifetime services provided by the three properties are obtained on application startup and shutdown notice, the notice was originally issued by the three methods corresponding to the.

public class ApplicationLifetime : IHostApplicationLifetime
{
    private readonly ILogger<ApplicationLifetime> _logger;
    private readonly CancellationTokenSource _startedSource;
    private readonly CancellationTokenSource _stoppedSource;
    private readonly CancellationTokenSource _stoppingSource;

    public ApplicationLifetime(ILogger<ApplicationLifetime> logger)
    {
        _startedSource = new CancellationTokenSource();
        _stoppedSource = new CancellationTokenSource();
        _stoppingSource = new CancellationTokenSource();
        _logger = logger;
    }

    private void ExecuteHandlers(CancellationTokenSource cancel)
    {
        if (!cancel.IsCancellationRequested)
        {
            cancel.Cancel(false);
        }
    }

    public void NotifyStarted()
    {
        try
        {
            this.ExecuteHandlers(this._startedSource);
        }
        catch (Exception exception)
        {
            _logger.ApplicationError(6, "An error occurred starting the application",exception);
        }
    }

    public void NotifyStopped()
    {
        try
        {
            ExecuteHandlers(this._stoppedSource);
        }
        catch (Exception exception)
        {
            _logger.ApplicationError(8, "An error occurred stopping the application",exception);
        }
    }

    public void StopApplication()
    {
        CancellationTokenSource source = this._stoppingSource;
        lock (source)
        {
            try
            {
                ExecuteHandlers(this._stoppingSource);
            }
            catch (Exception exception)
            {
                _logger.ApplicationError(7, "An error occurred stopping the application", exception);
            }
        }
    }

    public CancellationToken ApplicationStarted => _startedSource.Token;
    public CancellationToken ApplicationStopped => _stoppedSource.Token;
    public CancellationToken ApplicationStopping => _stoppingSource.Token;
}

Fourth, the use IHostApplicationLifetime close the application

We next through a simple example to demonstrate how to use IHostApplicationLifetime service to shut down the entire carrier applications. We define this as a bearer service FakeHostedService in a console application. In FakeHostedService type constructor, we injected IHostApplicationLifetime service. After obtaining CancellationToken object whose property returns three, we were registered on them a callback, the callback operation by outputting a corresponding character so that we know when the application is started and closed on the console.

public sealed class FakeHostedService : IHostedService
{
    private readonly IHostApplicationLifetime _lifetime;
    private IDisposable _tokenSource;

    public FakeHostedService(IHostApplicationLifetime lifetime)
    {
        _lifetime = lifetime;
        _lifetime.ApplicationStarted.Register(() => Console.WriteLine("[{0}]Application started", DateTimeOffset.Now));
        _lifetime.ApplicationStopping.Register(() => Console.WriteLine("[{0}]Application is stopping.", DateTimeOffset.Now));
        _lifetime.ApplicationStopped.Register(() => Console.WriteLine("[{0}]Application stopped.", DateTimeOffset.Now));
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token.Register(_lifetime.StopApplication);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _tokenSource?.Dispose();
        return Task.CompletedTask;
    }
}

In StartAsync implemented method, we use as a way to call IHostApplicationLifetime service after 5 seconds StopApplication method to close the entire application. Finally, this FakeHostedService service carried in the following manner in the current application.

class Program
{
    static void Main()
    {
        new HostBuilder()
            .ConfigureServices(svcs => svcs.AddHostedService<FakeHostedService>())
            .Build()
            .Run();
    }
}

The results of this program on the console output below shown after operation, three messages generated from the time interval we can determine the current application is carried by StopApplication FakeHostedService IHostApplicationLifetime method calls and services closed. (Source code here download)

10-8

Five, Run extension methods

If we call the extension method IHost object Run, it calls StartAsync method internally, then it will continue to wait forever until it receives notification of the application is closed. When the object is an object IHost use IHostApplicationLifetime service receives notification about the application shut down, it calls itself StopAsync method, then it will return for calling the Run method. Start IHost objects until the application is closed this realization is reflected in the following this WaitForShutdownAsync extension methods.

public static class HostingAbstractionsHostExtensions
{
    public static async Task WaitForShutdownAsync(this IHost host, CancellationToken token = default)
    {
        var applicationLifetime = host.Services.GetService<IHostApplicationLifetime>();
        token.Register(state => ((IHostApplicationLifetime)state).StopApplication(), applicationLifetime);

        var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
        applicationLifetime.ApplicationStopping.Register(state =>
        {
            var tcs = (TaskCompletionSource<object>)state;
            tcs.TrySetResult(null);
        }, waitForStop);

        await waitForStop.Task;
        await host.StopAsync();
    }
}

WaitForShutdown following method is a synchronous version of the above method of this WaitForShutdownAsync. RunAsync implemented method of synchronization and asynchronous Run method is also reflected in the following code fragment. In addition, the following code fragment and is also provided Start StopAsync two expansion methods, the former method may be considered synchronous version StartAsync, which may specify a timeout period when the object IHost closed.

public static class HostingAbstractionsHostExtensions
{
    public static void WaitForShutdown(this IHost host) => host.WaitForShutdownAsync().GetAwaiter().GetResult();
    public static void Run(this IHost host) => host.RunAsync().GetAwaiter().GetResult();
    public static async Task RunAsync(this IHost host, CancellationToken token = default)
    {
        try
        {
            await host.StartAsync(token);
            await host.WaitForShutdownAsync(token);
        }
        finally
        {
            host.Dispose();
        }
    }
    public static void Start(this IHost host) => host.StartAsync().GetAwaiter().GetResult();
    public static Task StopAsync(this IHost host, TimeSpan timeout) => host.StopAsync(new CancellationTokenSource(timeout).Token);
}

Service bearer system [1]: a long-running service bearer [Part]
service bearer system [2]: bearer services running time [next]
service bearer system [3]: General Design [Part]
service bearer system [4]: general design [Part II]
service bearer system [5]: bearer service start process [Part]
service bearer system [6]: bearer service start process [Part II]

Guess you like

Origin www.cnblogs.com/artech/p/inside-asp-net-core-09-03.html
Recommended