fix(legacy): complete hosted module cleanup

This commit is contained in:
2026-08-29 20:34:39 +08:00
parent 176952d52c
commit 9f5f548dea
15 changed files with 704 additions and 422 deletions
+8 -81
View File
@@ -157,7 +157,6 @@ namespace Lskj.PubModuleDetail
string guid = this.Tag + "";
if (string.IsNullOrWhiteSpace(guid))
{
this.mControl.ReleaseResourcesForDispose();
return;
}
DllModule m = Manager.ModuleForms[guid];
@@ -180,7 +179,6 @@ namespace Lskj.PubModuleDetail
}
}
}
// FormClosing fires before the control tree is disposed. Release the
// DevExpress grids and their native resources as soon as the close is
// confirmed; waiting for FrmMain.Dispose leaves GDI handles alive
@@ -232,91 +230,20 @@ namespace Lskj.PubModuleDetail
this.FormClosing -= OnClose;
this.Disposed -= OnFrmMainDisposed;
// StaticControl performs the module-wide cache cleanup after the
// shell has confirmed the close. Remove only this form's cache key
// here; clearing the whole shared dictionary from a Disposed event
// could affect another tab that still uses the same model cache.
Dictionary<object, Hashtable> dataCaches =
Model != null ? Model.DataCaches : null;
HashSet<Task> completedTasks;
if (dataCaches == null ||
!TryDetachCompletedCacheTasks(dataCaches, out completedTasks))
{
return;
}
DisposeCompletedCacheTasks(completedTasks);
}
/// <summary>
/// 释放模块预加载缓存中已完成任务的等待句柄。
/// Task.Result 在等待时可能创建底层等待对象,仅清空字典
/// 不会立即释放这些句柄。
/// </summary>
private static void DisposeCompletedCacheTasks(IEnumerable<Task> tasks)
{
foreach (Task task in tasks)
{
try
{
task.Dispose();
}
catch (ObjectDisposedException)
{
}
}
}
/// <summary>
/// 仅当并行初始化全部完成时,才在同一同步区间摘除缓存任务。
/// AddTask 使用同一个字典实例加锁,避免检查后又插入新任务。
/// </summary>
private static bool TryDetachCompletedCacheTasks(
Dictionary<object, Hashtable> dataCaches,
out HashSet<Task> completedTasks)
{
completedTasks = new HashSet<Task>();
try
{
lock (dataCaches)
{
foreach (Hashtable cacheValues in dataCaches.Values)
{
if (cacheValues == null)
{
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;
if (dataCaches != null)
dataCaches.RemoveCache(this);
}
catch (InvalidOperationException)
catch (Exception exception)
{
completedTasks.Clear();
return false;
Debug.WriteLine("移除窗体动态缓存引用失败:" + exception);
}
}
}