Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
235 views
in Technique[技术] by (71.8m points)

c# - How to access the members of the background service injected with AddSingleton<T>

In the asp.netcore web api project,there is a background service named TimedHostedService injected through AddSingleton<>,When accessing members [ExecutionCount] of this service from the controller,the value always equals to 0,When the member [ExecutionCount] is set to static,the value is changed,I do not know why? Must the property [ExecutionCount] be static?

TimedHostedService:

public class TimedHostedService : IHostedService, IDisposable
{
    private int executionCount = 0;
    private readonly ILogger<TimedHostedService> _logger;
    private Timer _timer;

    public int ExecutionCount
    {
        get { return executionCount; }
        set { executionCount = value; }
    }

    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero,
            TimeSpan.FromSeconds(1));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        var count = Interlocked.Increment(ref executionCount);

        _logger.LogInformation(
            "Timed Hosted Service is working. Count: {Count}", count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Injected through AddSingleton<>:

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<TimedHostedService>();
        services.AddControllers();
    }

 public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var hostBuilder = Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .ConfigureServices(services =>
            {
                services.AddHostedService<TimedHostedService>();
            })
            .UseContentRoot(Directory.GetCurrentDirectory())

        return hostBuilder;
    }

Access the property [ExecutionCount] from WeatherForecastController:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    private readonly TimedHostedService _timedHostedService;

    public WeatherForecastController(ILogger<WeatherForecastController> logger,TimedHostedService timedHostedService)
    {
        _logger = logger;
        _timedHostedService = timedHostedService;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        int timeValue = _timedHostedService.ExecutionCount;
        _logger.LogInformation("ExecutionCount:{0}", timeValue);

        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
question from:https://stackoverflow.com/questions/65914969/how-to-access-the-members-of-the-background-service-injected-with-addsingletont

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You add two instances of your service to the service collection. The line

services.AddSingleton<TimedHostedService>();

adds the instance your controller gets via dependency injection and the line

services.AddHostedService<TimedHostedService>();

adds the instance that is running as a hosted service.

Try the following:

services.AddHostedService((sp) => sp.GetRequiredService<TimedHostedService>());
services.AddSingleton<TimedHostedService>();

It is important to keep this sequence. This will add the hosted service to the service collection (as singleton) and use the same instance for the actual hosted service.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...