如何访问用AddSingleton<T>注入的后台服务成员

zhi*_*iyw 2 c# dependency-injection asp.net-core

在asp.netcore web api项目中,有一个名为TimedHostedService的后台服务,通过AddSingleton<>注入,当从控制器访问该服务的成员[ ExecutionCount ]时,该值始终等于0,当设置成员[ ExecutionCount ]时改为static,值就变了,不知道为什么?属性 [ ExecutionCount ] 必须是静态的吗?

\n

定时托管服务:

\n
public class TimedHostedService : IHostedService, IDisposable\n{\n    private int executionCount = 0;\n    private readonly ILogger<TimedHostedService> _logger;\n    private Timer _timer;\n\n    public int ExecutionCount\n    {\n        get { return executionCount; }\n        set { executionCount = value; }\n    }\n\n    public TimedHostedService(ILogger<TimedHostedService> logger)\n    {\n        _logger = logger;\n    }\n\n    public Task StartAsync(CancellationToken stoppingToken)\n    {\n        _logger.LogInformation("Timed Hosted Service running.");\n\n        _timer = new Timer(DoWork, null, TimeSpan.Zero,\n            TimeSpan.FromSeconds(1));\n\n        return Task.CompletedTask;\n    }\n\n    private void DoWork(object state)\n    {\n        var count = Interlocked.Increment(ref executionCount);\n\n        _logger.LogInformation(\n            "Timed Hosted Service is working. Count: {Count}", count);\n    }\n\n    public Task StopAsync(CancellationToken stoppingToken)\n    {\n        _logger.LogInformation("Timed Hosted Service is stopping.");\n\n        _timer?.Change(Timeout.Infinite, 0);\n\n        return Task.CompletedTask;\n    }\n\n    public void Dispose()\n    {\n        _timer?.Dispose();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

通过AddSingleton<>\xef\xbc\x9a注入

\n
 public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddSingleton<TimedHostedService>();\n        services.AddControllers();\n    }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n    {\n        var hostBuilder = Host.CreateDefaultBuilder(args)\n            .ConfigureWebHostDefaults(webBuilder =>\n            {\n                webBuilder.UseStartup<Startup>();\n            })\n            .ConfigureServices(services =>\n            {\n                services.AddHostedService<TimedHostedService>();\n            })\n            .UseContentRoot(Directory.GetCurrentDirectory())\n\n        return hostBuilder;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

从 WeatherForecastController访问属性 [ ExecutionCount ]:

\n
[ApiController]\n[Route("[controller]")]\npublic class WeatherForecastController : ControllerBase\n{\n    private static readonly string[] Summaries = new[]\n    {\n        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"\n    };\n\n    private readonly ILogger<WeatherForecastController> _logger;\n\n    private readonly TimedHostedService _timedHostedService;\n\n    public WeatherForecastController(ILogger<WeatherForecastController> logger,TimedHostedService timedHostedService)\n    {\n        _logger = logger;\n        _timedHostedService = timedHostedService;\n    }\n\n    [HttpGet]\n    public IEnumerable<WeatherForecast> Get()\n    {\n        int timeValue = _timedHostedService.ExecutionCount;\n        _logger.LogInformation("ExecutionCount:{0}", timeValue);\n\n        var rng = new Random();\n        return Enumerable.Range(1, 5).Select(index => new WeatherForecast\n        {\n            Date = DateTime.Now.AddDays(index),\n            TemperatureC = rng.Next(-20, 55),\n            Summary = Summaries[rng.Next(Summaries.Length)]\n        })\n        .ToArray();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Tho*_*ösi 7

您将服务的两个实例添加到服务集合中。线路

services.AddSingleton<TimedHostedService>();
Run Code Online (Sandbox Code Playgroud)

添加控制器通过依赖注入获取的实例和行

services.AddHostedService<TimedHostedService>();
Run Code Online (Sandbox Code Playgroud)

添加作为托管服务运行的实例。

请尝试以下操作:

services.AddHostedService((sp) => sp.GetRequiredService<TimedHostedService>());
services.AddSingleton<TimedHostedService>();
Run Code Online (Sandbox Code Playgroud)

保持这个顺序很重要。这会将托管服务添加到服务集合(作为单例),并为实际托管服务使用相同的实例。