ASP.NET Core AddHostedService 和 AddSingleton 关系

我一起使用 AddSingleton 和 AddHostedService 在后端有一个长时间运行的服务(BackgroundService),而控制器访问相同的服务来获取数据。这是我发现的:

  1. 如果同时使用 AddSingleton 和 AddHostedService,BackgroundService 会被初始化两次(不是 Singleton)。控制器只能访问在 AddSingleton 中创建的那个。

调试输出(构造函数调用了两次,以秒为单位查看差异)

BGService 构造函数 service addGame:games count is 1 BGService 构造函数 service addGame:games count is 1 ExecuteAsync 1 :games count is 1: [ "CONSTRUCTOR GAME AT 10/29/2021 10:37:25 AM(0)" ] ...... ExecuteAsync 7 :games count is 1:[ "CONSTRUCTOR GAME AT 10/29/2021 10:37:25 AM(0)" ] service addGame:games count is 2 After AddGame: [
"CONSTRUCTOR GAME AT 10/29/2021 10:37:24 AM(0)", "GAME 0(1)" ]

  1. If only AddSingleton was used, it worked.

  2. If only AddHostedService was used, the BackgroundService was running, but DI not working in controller (Exception).

**> fail:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware1 执行请求时发生未处理的异常。 System.InvalidOperationException:尝试激活“CoreServiceSignalRSample.Controllers.WeatherForecastController”时,无法解析“CoreServiceSignalRSample.service.IBGService”类型的服务。
在 Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp,类型类型,类型 requiredBy,布尔 isDefaultParameterRequired)
在 lambda_method(Closure , IServiceProvider , Object [] )**

My question is, what is the proper way to DI a BackgroundService and why AddHostedService is recommended?

The sample code can be found at https://github.com/huangpat/CoreServiceSignalRSample .

Startup.cs 配置服务

    services.AddSingleton<IBGService>(new BGService());
    services.AddHostedService<BGService>();

BGSercie.cs

private List<string> games;

public BGService()
{
    Console.WriteLine("BGService constructor");
    this.games = new List<string>();
    this.addGame("Constructor Game at " + DateTime.Now.ToString());
}

public async Task<bool> addGame(string fGame)
{
    if (this.games.Count <= 20)
    {
        this.games.Add(fGame.ToUpper() + "(" + Convert.ToString(this.games.Count) + ")");
        Console.WriteLine("service addGame:games count is " + Convert.ToString(this.games.Count));
        return true;
    }
    else
    {
        return false;
    }
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    int i = 0;
    while (true)
    {
        i++;
        if (games.Count == 0)
        {
            this.addGame("ExecuteAsync Game at " + DateTime.Now.ToString());
        }
        JsonSerializer js = new JsonSerializer();

        Console.WriteLine("ExecuteAsync {1} :games count is {0}:{2}", this.games.Count, i, JsonConvert.SerializeObject(this.games, Formatting.Indented));

        await Task.Delay(1000 * 2 * 5);
    }
    //throw new NotImplementedException();

    /

/ 使用线程池启动集合中的每个游戏 }

stack overflow ASP.NET Core AddHostedService and AddSingleton relationship
原文答案
author avatar

接受的答案

每个注册都会使用自己的解析规则创建自己的类型描述符(即默认情况下它将使用相应的构造函数)。您可以使用注册实现工厂来解决它:

services.AddSingleton<BGService>();
services.AddSingleton<IBGService>(provider => provider.GetRequiredService<BGService>());
services.AddHostedService<BGService>(provider => provider.GetRequiredService<BGService>());

答案: