.NET 9控制器中ConcurrentDictionary在IIS环境下读写不一致问题
问题原因与解决方案
核心问题
.NET 默认将控制器注册为**瞬态(Transient)**服务,每一次HTTP请求都会创建一个全新的控制器实例。你在POST请求中更新的是当前控制器实例的myConcurrentDictionary,但GET请求会触发新的控制器实例创建,它的字典自然是空的——两个请求操作的根本不是同一个字典对象。
可行解决方案
1. 将字典声明为静态字段
直接把myConcurrentDictionary定义为控制器类的静态成员,这样所有控制器实例都会共享同一个字典实例:
public class MyController : ControllerBase { // 静态字段,全局共享同一个实例 private static readonly ConcurrentDictionary<string, object> _myConcurrentDictionary = new(); [HttpPost] public IActionResult UpdateData(string key, object value) { _myConcurrentDictionary.AddOrUpdate(key, value, (k, existingVal) => value); return Ok(); } [HttpGet] public IActionResult GetData(string key) { if (_myConcurrentDictionary.TryGetValue(key, out var value)) { return Ok(value); } return NotFound(); } }
注意:静态字段的生命周期和应用程序域绑定,应用重启后数据会丢失;如果是多服务器部署,静态字段无法跨节点共享数据。
2. 用依赖注入注册单例服务(推荐)
这是更符合.NET设计规范的方案,把字典封装成单例服务,通过依赖注入注入到控制器中:
步骤1:定义数据存储服务(可选但推荐接口化)
public interface IInMemoryDataStore { ConcurrentDictionary<string, object> GetDictionary(); } public class InMemoryDataStore : IInMemoryDataStore { private readonly ConcurrentDictionary<string, object> _dataDictionary = new(); public ConcurrentDictionary<string, object> GetDictionary() { return _dataDictionary; } }
步骤2:在Program.cs中注册为单例
builder.Services.AddSingleton<IInMemoryDataStore, InMemoryDataStore>();
步骤3:控制器中注入使用
public class MyController : ControllerBase { private readonly ConcurrentDictionary<string, object> _myConcurrentDictionary; // 通过构造函数注入单例服务 public MyController(IInMemoryDataStore dataStore) { _myConcurrentDictionary = dataStore.GetDictionary(); } [HttpPost] public IActionResult UpdateData(string key, object value) { _myConcurrentDictionary.AddOrUpdate(key, value, (k, existingVal) => value); return Ok(); } [HttpGet] public IActionResult GetData(string key) { if (_myConcurrentDictionary.TryGetValue(key, out var value)) { return Ok(value); } return NotFound(); } }
优势:遵循依赖注入原则,后续可以轻松替换为分布式缓存(如Redis),也便于编写单元测试。
3. 分布式缓存(多实例/持久化场景)
如果你的应用是多服务器部署,或者需要数据持久化,内存级别的存储方案就不适用了。此时可以使用.NET内置的IDistributedCache,或者直接集成Redis等分布式缓存组件,替代内存中的ConcurrentDictionary。
内容的提问来源于stack exchange,提问作者D052057
相关产品推荐
相关产品推荐

