首页 > 解决方案 > 在 ASP.NET Core 中注册 HostedService 的正确方法。AddHostedService 与 AddSingleton

问题描述

在 ASP.NET Core 2.1 中注册自定义托管服务的正确方法是什么?例如,我有一个从BackgroundService派生的自定义托管服务,名为MyHostedService. 我应该如何注册?

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

或者

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

?

在这里我们可以看到第一种情况,但这里有第二种情况。

这些方法是否相同?

标签: c#asp.net-core.net-coredependency-injectionasp.net-core-hosted-services

解决方案


更新

过去,HostedService 是一个长期存在的瞬态,有效地充当单例。从 .NET Core 3.1开始,它是一个实际的 Singleton


采用AddHostedService

托管服务不仅仅是单例服务。运行时“知道”它,可以告诉它通过调用开始StartAsync或通过调用停止,StopAsync()例如,每当应用程序池被回收时。在 Web 应用程序本身终止之前,运行时可以等待托管服务完成。

正如文档解释的那样,可以通过在托管服务的工作方法中创建范围来使用范围服务。瞬态服务也是如此。

为此,必须将 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>();
            …
        }
    }
    …
}

推荐阅读