.NET Core 3中如何通过依赖注入在Worker Service与WebAPI间传递公共对象
解决方案
我来帮你解决这个问题——你需要的是把StatusInfo注册为单例服务,这样Worker服务和WebAPI就能共享同一个实例,实现双向的数据交互。以下是具体的实现步骤和代码示例:
1. 注册共享状态对象
在CreateHostBuilder的ConfigureServices方法中,将StatusInfo注册为单例服务。单例模式会确保整个应用生命周期内只存在一个StatusInfo实例,Worker和WebAPI都会拿到同一个对象:
.ConfigureServices((hostContext, services) => { services.AddOptions(); // 注册单例状态对象,全局共享同一实例 services.AddSingleton<StatusInfo>(); services.AddHostedService<Worker>(); });
2. 在Worker中注入并更新状态
修改Worker类的构造函数,通过依赖注入获取StatusInfo实例,然后在后台任务的执行逻辑中更新状态属性:
public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; private readonly StatusInfo _statusInfo; // 通过构造函数注入共享状态对象 public Worker(ILogger<Worker> logger, StatusInfo statusInfo) { _logger = logger; _statusInfo = statusInfo; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var random = new Random(); while (!stoppingToken.IsCancellationRequested) { // 模拟任务执行,更新状态信息 _statusInfo.LastRun = DateTime.Now; _statusInfo.LastAdded = random.Next(1, 100); _statusInfo.LastUpdated = random.Next(1, 50); _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(5000, stoppingToken); } } }
3. 在WebAPI中注入并查询状态
在你的WebAPI控制器(比如健康检查专用控制器)中,同样通过构造函数注入StatusInfo,然后暴露接口返回最新的状态信息:
[ApiController] [Route("api/health")] public class HealthCheckController : ControllerBase { private readonly StatusInfo _statusInfo; public HealthCheckController(StatusInfo statusInfo) { _statusInfo = statusInfo; } [HttpGet("worker-status")] public IActionResult GetWorkerStatus() { // 直接返回共享的状态数据 return Ok(new { WorkerLastRunTime = _statusInfo.LastRun, LastAddedItems = _statusInfo.LastAdded, LastUpdatedItems = _statusInfo.LastUpdated, ServiceStatus = "Running" }); } }
4. 线程安全优化(可选但推荐)
由于Worker是后台线程,WebAPI是请求线程,两者会同时访问StatusInfo,为了避免多线程下的状态不一致问题,可以给StatusInfo的属性加锁:
public class StatusInfo { private readonly object _lockObj = new object(); private DateTime _lastRun; private int _lastAdded; private int _lastUpdated; public DateTime LastRun { get { lock (_lockObj) return _lastRun; } set { lock (_lockObj) _lastRun = value; } } public int LastAdded { get { lock (_lockObj) return _lastAdded; } set { lock (_lockObj) _lastAdded = value; } } public int LastUpdated { get { lock (_lockObj) return _lastUpdated; } set { lock (_lockObj) _lastUpdated = value; } } }
这样就能实现Worker和WebAPI之间的状态共享了——Worker更新的状态会实时同步到WebAPI可以读取的实例中,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

