web-dev-qa-db-ja.com

HostedServiceをASP.NET Coreに登録する適切な方法。 AddHostedServiceとAddSingleton

ASP.NET Core 2.1でカスタムホストサービスを登録する適切な方法は何ですか?たとえば、 BackgroundService named MyHostedServiceから派生したカスタムホストサービスがあります。どうすれば登録できますか?

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    //...
    services.AddSingleton<IHostedService, MyHostedService>();
}

または

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    //...
    services.AddHostedService<MyHostedService>();
}

ここ 最初のケースを見ることができますが、 ここ 2番目のケースがあります。

これらの方法は同等ですか?

19
Denis Babarykin

それらは似ていますが、完全ではありません

AddHostedServiceMicrosoft.Extensions.Hosting.Abstractionsの一部です。

ServiceCollectionHostedServiceExtensions クラスのMicrosoft.Extensions.Hosting.Abstractionsに属します

using Microsoft.Extensions.Hosting;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionHostedServiceExtensions
    {
        /// <summary>
        /// Add an <see cref="IHostedService"/> registration for the given type.
        /// </summary>
        /// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>
        /// <returns>The original <see cref="IServiceCollection"/>.</returns>
        public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services)
            where THostedService : class, IHostedService
            => services.AddTransient<IHostedService, THostedService>();
    }
}

Transientではなく、Singletonライフタイムスコープを使用していることに注意してください。

内部的には、フレームワークはホストされているすべてのサービスを別のサービスに追加します HostedServiceExecutor

public HostedServiceExecutor(ILogger<HostedServiceExecutor> logger, 
    IEnumerable<IHostedService> services) //<<-- note services collection
{
    _logger = logger;
    _services = services;
}

起動時に WebHost Constructor を介したシングルトンです。

_applicationServiceCollection.AddSingleton<HostedServiceExecutor>();
6
Nkosi

AddHostedServiceを使用

ホスト型サービスは、単なるシングルトンサービスではありません。ランタイムはそれを「認識」し、StartAsyncを呼び出すことで開始するように、またはアプリケーションプールがリサイクルされるたびにStopAsync()を呼び出すことで停止するように指示できます。ランタイムは、Webサービス自体が終了する前に、ホストされたサービスが終了するのを待つことができます。

ドキュメントで説明 スコープサービスcanは、ホストされたサービスのワーカーメソッド内にスコープを作成することで消費されます。同じことが一時的なサービスにも当てはまります。

これを行うには、IServicesProviderまたはIServiceScopeFactoryをホストされたサービスのコンストラクターに挿入し、スコープの作成に使用する必要があります。

ドキュメントから借用すると、サービスのコンストラクターとワーカーメソッドは次のようになります。

public IServiceProvider Services { get; }

public ConsumeScopedServiceHostedService(IServiceProvider services, 
    ILogger<ConsumeScopedServiceHostedService> logger)
{
    Services = services;
    _logger = logger;
}


private void DoWork()
{
    using (var scope = Services.CreateScope())
    {
        var scopedProcessingService = 
            scope.ServiceProvider
                .GetRequiredService<IScopedProcessingService>();

        scopedProcessingService.DoWork();
    }
}

この関連する質問 は、ホストされたサービスで一時的なDbContextを使用する方法を示しています。

public class MyHostedService : IHostedService
{
    private readonly IServiceScopeFactory scopeFactory;

    public MyHostedService(IServiceScopeFactory scopeFactory)
    {
        this.scopeFactory = scopeFactory;
    }

    public void DoWork()
    {
        using (var scope = scopeFactory.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
            …
        }
    }
    …
}
17