fix: synchronize module data cache cleanup
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace Lskj.Report
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
model.DataCaches.Clear();
|
model.DataCaches.ClearCaches();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user