fix: synchronize module data cache cleanup
This commit is contained in:
@@ -211,13 +211,14 @@ namespace Lskj.PubModuleDetail
|
||||
|
||||
Dictionary<object, Hashtable> dataCaches =
|
||||
Model != null ? Model.DataCaches : null;
|
||||
if (dataCaches == null || !AreDataCacheTasksCompleted(dataCaches))
|
||||
HashSet<Task> completedTasks;
|
||||
if (dataCaches == null ||
|
||||
!TryDetachCompletedCacheTasks(dataCaches, out completedTasks))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DisposeCompletedCacheTasks(dataCaches);
|
||||
dataCaches.Clear();
|
||||
DisposeCompletedCacheTasks(completedTasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -225,34 +226,10 @@ namespace Lskj.PubModuleDetail
|
||||
/// Task.Result 在等待时可能创建底层等待对象,仅清空字典
|
||||
/// 不会立即释放这些句柄。
|
||||
/// </summary>
|
||||
private static void DisposeCompletedCacheTasks(
|
||||
Dictionary<object, Hashtable> dataCaches)
|
||||
private static void DisposeCompletedCacheTasks(IEnumerable<Task> tasks)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!task.IsCompleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
task.Dispose();
|
||||
@@ -264,27 +241,58 @@ namespace Lskj.PubModuleDetail
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 并行初始化仍在运行时不能清空缓存字典,后台任务还会读取或追加其中的数据。
|
||||
/// 仅当并行初始化全部完成时,才在同一同步区间摘除缓存任务。
|
||||
/// AddTask 使用同一个字典实例加锁,避免检查后又插入新任务。
|
||||
/// </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
|
||||
{
|
||||
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 (task != null && !task.IsCompleted)
|
||||
if (cacheValues == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
completedTasks.Clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user