diff --git a/XCode/Configuration/DbConfigProvider.cs b/XCode/Configuration/DbConfigProvider.cs index decd5206f..51c8a4598 100644 --- a/XCode/Configuration/DbConfigProvider.cs +++ b/XCode/Configuration/DbConfigProvider.cs @@ -26,6 +26,9 @@ public class DbConfigProvider : ConfigProvider public Int32 Period { get; set; } = 15; private IDictionary? _cache; + + /// 保存操作锁,防止与定时刷新冲突 + private readonly Object _saveLock = new(); #endregion #region 方法 @@ -215,13 +218,26 @@ public class DbConfigProvider : ConfigProvider /// 保存配置树到数据源 public override Boolean SaveAll() { - var list = Parameter.FindAllByUserID(UserId, Category); - Save(list, Root, null); + lock (_saveLock) + { + XTrace.WriteLine("[{0}/{1}]开始保存配置", Category, UserId); - // 通知绑定对象,配置数据有改变 - NotifyChange(); + var list = Parameter.FindAllByUserID(UserId, Category); + Save(list, Root, null); - return true; + // 重新加载配置以更新缓存,避免被DoRefresh覆盖 + var dic = GetAll(); + if (dic != null) + { + SaveCache(dic); + XTrace.WriteLine("[{0}/{1}]配置保存完成,已更新缓存", Category, UserId); + } + + // 通知绑定对象,配置数据有改变 + NotifyChange(); + + return true; + } } void Save(IList list, IConfigSection root, String? prefix) @@ -253,6 +269,9 @@ public class DbConfigProvider : ConfigProvider pi.Save(); } } + + // 确保所有数据库操作完成,避免事务延迟导致的读取不一致 + Thread.Sleep(10); } #endregion @@ -290,35 +309,49 @@ public class DbConfigProvider : ConfigProvider /// protected void DoRefresh(Object state) { - using var showSql = Parameter.Meta.Session.Dal.Session.SetShowSql(false); - - var dic = GetAll(); - if (dic == null) return; - - var changed = new Dictionary(); - if (_cache != null) + // 使用TryEnter避免在保存操作期间阻塞 + if (!Monitor.TryEnter(_saveLock, 100)) { - foreach (var item in dic) - { - // 跳过备注 - if (item.Key[0] == '#') continue; - if (!_cache.TryGetValue(item.Key, out var v) || v + "" != item.Value + "") - { - changed.Add(item.Key, item.Value); - } - } + // 如果无法获取锁,说明正在保存,跳过本次刷新 + return; } - if (changed.Count > 0) + try { - XTrace.WriteLine("[{0}/{1}]配置改变,重新加载如下键:{2}", Category, UserId, changed.ToJson()); + using var showSql = Parameter.Meta.Session.Dal.Session.SetShowSql(false); - Root = Build(dic); + var dic = GetAll(); + if (dic == null) return; - // 缓存 - SaveCache(dic); + var changed = new Dictionary(); + if (_cache != null) + { + foreach (var item in dic) + { + // 跳过备注 + if (item.Key[0] == '#') continue; + if (!_cache.TryGetValue(item.Key, out var v) || v + "" != item.Value + "") + { + changed.Add(item.Key, item.Value); + } + } + } - NotifyChange(); + if (changed.Count > 0) + { + XTrace.WriteLine("[{0}/{1}]定时检测到配置改变,重新加载如下键:{2}", Category, UserId, changed.ToJson()); + + Root = Build(dic); + + // 缓存 + SaveCache(dic); + + NotifyChange(); + } + } + finally + { + Monitor.Exit(_saveLock); } } #endregion