fix: synchronize module data cache cleanup

This commit is contained in:
2026-08-15 18:39:26 +08:00
parent d098dde830
commit a65dfab897
11 changed files with 126 additions and 71 deletions
@@ -219,7 +219,7 @@ namespace Lskj.BaseAccraditation
} }
if (SysModel != null && SysModel.DataCaches != null) if (SysModel != null && SysModel.DataCaches != null)
{ {
SysModel.DataCaches.Remove(this); SysModel.DataCaches.RemoveCache(this);
} }
} }
catch catch
+1 -1
View File
@@ -94,7 +94,7 @@ namespace Lskj.Control
{ {
if (SysModel != null && SysModel.DataCaches != null) if (SysModel != null && SysModel.DataCaches != null)
{ {
SysModel.DataCaches.Remove(this); SysModel.DataCaches.RemoveCache(this);
} }
} }
catch catch
+1 -1
View File
@@ -6892,7 +6892,7 @@ namespace Lskj.Control.Model
{ {
if (Model != null && Model.DataCaches != null) if (Model != null && Model.DataCaches != null)
{ {
Model.DataCaches.Remove(this); Model.DataCaches.RemoveCache(this);
} }
} }
catch catch
+1 -1
View File
@@ -261,7 +261,7 @@ namespace Lskj.Control
{ {
if (Model != null && Model.DataCaches != null) if (Model != null && Model.DataCaches != null)
{ {
Model.DataCaches.Remove(this); Model.DataCaches.RemoveCache(this);
} }
} }
catch catch
+1 -1
View File
@@ -193,7 +193,7 @@ namespace Lskj.Control
{ {
if (Model != null && Model.DataCaches != null) if (Model != null && Model.DataCaches != null)
{ {
Model.DataCaches.Remove(this); Model.DataCaches.RemoveCache(this);
} }
} }
catch catch
+1 -1
View File
@@ -3780,7 +3780,7 @@ namespace Lskj.Control
{ {
if (Model != null && Model.DataCaches != null) if (Model != null && Model.DataCaches != null)
{ {
Model.DataCaches.Remove(this); Model.DataCaches.RemoveCache(this);
} }
} }
catch catch
@@ -121,7 +121,7 @@ namespace Lskj.Control
{ {
if (Model != null && Model.DataCaches != null) if (Model != null && Model.DataCaches != null)
{ {
Model.DataCaches.Remove(this); Model.DataCaches.RemoveCache(this);
} }
} }
catch catch
@@ -89,7 +89,7 @@ namespace Lskj.PubAccraditation
} }
if (SysModel != null && SysModel.DataCaches != null) if (SysModel != null && SysModel.DataCaches != null)
{ {
SysModel.DataCaches.Remove(this); SysModel.DataCaches.RemoveCache(this);
} }
} }
catch catch
+43 -35
View File
@@ -211,13 +211,14 @@ namespace Lskj.PubModuleDetail
Dictionary<object, Hashtable> dataCaches = Dictionary<object, Hashtable> dataCaches =
Model != null ? Model.DataCaches : null; Model != null ? Model.DataCaches : null;
if (dataCaches == null || !AreDataCacheTasksCompleted(dataCaches)) HashSet<Task> completedTasks;
if (dataCaches == null ||
!TryDetachCompletedCacheTasks(dataCaches, out completedTasks))
{ {
return; return;
} }
DisposeCompletedCacheTasks(dataCaches); DisposeCompletedCacheTasks(completedTasks);
dataCaches.Clear();
} }
/// <summary> /// <summary>
@@ -225,34 +226,10 @@ namespace Lskj.PubModuleDetail
/// Task.Result 在等待时可能创建底层等待对象,仅清空字典 /// Task.Result 在等待时可能创建底层等待对象,仅清空字典
/// 不会立即释放这些句柄。 /// 不会立即释放这些句柄。
/// </summary> /// </summary>
private static void DisposeCompletedCacheTasks( private static void DisposeCompletedCacheTasks(IEnumerable<Task> tasks)
Dictionary<object, Hashtable> dataCaches)
{ {
HashSet<Task> tasks = new HashSet<Task>();
foreach (Hashtable cache in dataCaches.Values)
{
if (cache == null)
{
continue;
}
foreach (object value in cache.Values)
{
Task task = value as Task;
if (task != null)
{
tasks.Add(task);
}
}
}
foreach (Task task in tasks) foreach (Task task in tasks)
{ {
if (!task.IsCompleted)
{
continue;
}
try try
{ {
task.Dispose(); task.Dispose();
@@ -264,27 +241,58 @@ namespace Lskj.PubModuleDetail
} }
/// <summary> /// <summary>
/// 并行初始化仍在运行时不能清空缓存字典,后台任务还会读取或追加其中的数据 /// 仅当并行初始化全部完成时,才在同一同步区间摘除缓存任务
/// AddTask 使用同一个字典实例加锁,避免检查后又插入新任务。
/// </summary> /// </summary>
private static bool AreDataCacheTasksCompleted(Dictionary<object, Hashtable> dataCaches) private static bool TryDetachCompletedCacheTasks(
Dictionary<object, Hashtable> dataCaches,
out HashSet<Task> completedTasks)
{ {
completedTasks = new HashSet<Task>();
try try
{ {
foreach (Hashtable cacheValues in dataCaches.Values) lock (dataCaches)
{ {
foreach (object value in cacheValues.Values) foreach (Hashtable cacheValues in dataCaches.Values)
{ {
Task task = value as Task; if (cacheValues == null)
if (task != null && !task.IsCompleted)
{ {
return false; continue;
}
foreach (object value in cacheValues.Values)
{
Task task = value as Task;
if (task == null)
{
continue;
}
try
{
if (!task.IsCompleted)
{
completedTasks.Clear();
return false;
}
}
catch (ObjectDisposedException)
{
continue;
}
completedTasks.Add(task);
} }
} }
dataCaches.Clear();
} }
return true; return true;
} }
catch (InvalidOperationException) catch (InvalidOperationException)
{ {
completedTasks.Clear();
return false; return false;
} }
} }
+1 -1
View File
@@ -115,7 +115,7 @@ namespace Lskj.Report
try try
{ {
model.DataCaches.Clear(); model.DataCaches.ClearCaches();
} }
catch (Exception ex) catch (Exception ex)
{ {
+74 -27
View File
@@ -197,26 +197,31 @@ namespace Lskj.Util
value = default; value = default;
return false; return false;
} }
if (dic.ContainsKey(control))
Task<T> task;
lock (dic)
{ {
if (dic[control].ContainsKey(key)) Hashtable cache;
{ if (!dic.TryGetValue(control, out cache) ||
Task<T> task = dic[control][key] as Task<T>; cache == null ||
value = task.Result; !cache.ContainsKey(key))
task.Dispose();
return true;
}
else
{ {
value = default; value = default;
return false; return false;
} }
task = cache[key] as Task<T>;
} }
else
if (task == null)
{ {
value = default; value = default;
return false; return false;
} }
value = task.Result;
task.Dispose();
return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -237,14 +242,23 @@ namespace Lskj.Util
{ {
try try
{ {
if (cachesDic.ContainsKey(control) && cachesDic[control].ContainsKey(key)) if (cachesDic == null)
{
return (Task<T>)cachesDic[control][key];
}
else
{ {
return default; return default;
} }
lock (cachesDic)
{
Hashtable cache;
if (cachesDic.TryGetValue(control, out cache) &&
cache != null &&
cache.ContainsKey(key))
{
return cache[key] as Task<T>;
}
}
return default;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -253,6 +267,36 @@ namespace Lskj.Util
} }
} }
/// <summary> /// <summary>
/// 在线程安全的同步区间内移除控件缓存。
/// </summary>
public static bool RemoveCache(this Dictionary<object, Hashtable> cachesDic, object control)
{
if (cachesDic == null)
{
return false;
}
lock (cachesDic)
{
return cachesDic.Remove(control);
}
}
/// <summary>
/// 在线程安全的同步区间内清空任务缓存。
/// </summary>
public static void ClearCaches(this Dictionary<object, Hashtable> cachesDic)
{
if (cachesDic == null)
{
return;
}
lock (cachesDic)
{
cachesDic.Clear();
}
}
/// <summary>
/// 添加任务 /// 添加任务
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
@@ -262,20 +306,23 @@ namespace Lskj.Util
/// <param name="task"></param> /// <param name="task"></param>
public static Task<T> AddTask<T>(this Dictionary<object, Hashtable> cachesDic, object control, string key, Task<T> task) public static Task<T> AddTask<T>(this Dictionary<object, Hashtable> cachesDic, object control, string key, Task<T> task)
{ {
Hashtable cachesHash = new Hashtable(); lock (cachesDic)
if (!cachesDic.ContainsKey(control))
{ {
cachesDic.Add(control, cachesHash); Hashtable cachesHash;
} if (!cachesDic.TryGetValue(control, out cachesHash) ||
else cachesHash == null)
{ {
cachesHash = cachesDic[control]; cachesHash = new Hashtable();
} cachesDic[control] = cachesHash;
cachesHash.Add(key, task); }
if (task.Status == TaskStatus.Created)
{ cachesHash.Add(key, task);
task.Start(SchedulerUtil); if (task.Status == TaskStatus.Created)
{
task.Start(SchedulerUtil);
}
} }
return task; return task;
} }