在asp.netcore web api项目中,有一个名为TimedHostedService的后台服务是通过AddSingleton<>注入(inject)的,当 Controller 访问该服务的成员[ExecutionCount]时,该值总是等于0,当成员[ExecutionCount]设置为static时,值发生变化,不知道为什么?属性 [ExecutionCount] 必须是静态的吗?
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();
}
}
通过AddSingleton<>注入(inject):
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;
}
从 WeatherForecastController 访问属性 [ExecutionCount]:
[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();
}
}
最佳答案
您将服务的两个实例添加到服务集合中。线路
services.AddSingleton<TimedHostedService>();
添加您的 Controller 通过依赖注入(inject)和行获取的实例
services.AddHostedService<TimedHostedService>();
添加作为托管服务运行的实例。
尝试以下操作:
services.AddHostedService((sp) => sp.GetRequiredService<TimedHostedService>());
services.AddSingleton<TimedHostedService>();
保持这个顺序很重要。这会将托管服务添加到服务集合(作为单例),并为实际托管服务使用相同的实例。
关于c# - 如何访问用AddSingleton<T>注入(inject)的后台服务的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65914969/