设备销毁处理

This commit is contained in:
hsc
2026-06-24 10:08:38 +08:00
parent cd3cbe7c35
commit c4470af013
2 changed files with 64 additions and 1 deletions

View File

@@ -15,11 +15,12 @@ namespace UIShare.GlobalVariable
/// 设备管理器:根据 <see cref="SystemConfig.DeviceList"/> 反射实例化所有启用的设备,
/// 通过 <see cref="IBaseInterface"/> 多态统一管理,避免为每种设备单独硬编码字段。
/// </summary>
public class DeviceManager
public class DeviceManager:IDisposable
{
private object _lockObj = new object();
public SystemConfig _systemConfig { get; set; }
private readonly GlobalInfo _globalInfo;
private readonly string _scopeName;
/// <summary>按 DeviceName 索引的设备字典,便于业务层按名取实例。</summary>
public IDictionary<string, IBaseInterface> DeviceMap { get; private set; }
@@ -32,6 +33,8 @@ namespace UIShare.GlobalVariable
{
_systemConfig = systemConfig;
_globalInfo = globalInfo;
// 用 SystemConfig.Title 作为作用域唯一标识,无需反查 ConfigDic
_scopeName = _systemConfig.Title;
InitDevices();
}
/// <summary>
@@ -108,6 +111,18 @@ namespace UIShare.GlobalVariable
DeviceMap[config.DeviceName] = instance;
}
// 第五步:将当前作用域注册到指纹的作用域列表,用于引用计数与安全销毁
if (!string.IsNullOrEmpty(_scopeName))
{
var scopeList = _globalInfo.DeviceAndScopeDic.GetOrAdd(fingerprint,
_ => new Lazy<List<string>>(() => new List<string>())).Value;
lock (scopeList)
{
if (!scopeList.Contains(_scopeName))
scopeList.Add(_scopeName);
}
}
LoggerHelper.Info($"已加载设备 [{config.DeviceName} / {config.DeviceType} / {config.ConnectionType}] 指纹={fingerprint}");
}
catch (Exception ex)
@@ -338,6 +353,50 @@ namespace UIShare.GlobalVariable
};
return Activator.CreateInstance(type, cfg) as IBaseInterface;
}
public void Dispose()
{
if (string.IsNullOrEmpty(_scopeName)) return;
// 遍历当前作用域用到的所有指纹,逐一移除本作用域的引用
var fingerprintsToRemove = new List<string>();
foreach (var kvp in _globalInfo.DeviceAndScopeDic)
{
string fingerprint = kvp.Key;
var scopeList = kvp.Value.IsValueCreated ? kvp.Value.Value : null;
if (scopeList == null) continue;
lock (scopeList)
{
scopeList.Remove(_scopeName);
// 引用归零 → 标记为待清理
if (scopeList.Count == 0)
fingerprintsToRemove.Add(fingerprint);
}
}
// 对引用归零的指纹:销毁设备实例 + 从全局池中移除
foreach (var fingerprint in fingerprintsToRemove)
{
// 尝试从 HardwarePool 取出并销毁
if (_globalInfo.HardwarePool.TryRemove(fingerprint, out var lazy))
{
if (lazy.IsValueCreated && lazy.Value is IBaseInterface device)
{
try { device.Close(); }
catch { /* 销毁时忽略异常 */ }
LoggerHelper.Info($"指纹 [{fingerprint}] 无作用域引用,已销毁设备实例。");
}
}
// 同步清除 DeviceAndScopeDic 中的空条目
_globalInfo.DeviceAndScopeDic.TryRemove(fingerprint, out _);
}
DeviceMap.Clear();
}
#endregion
}
}

View File

@@ -19,6 +19,9 @@ namespace UIShare.GlobalVariable
/// <summary>硬件指纹 → 设备实例的并发池,确保同一物理硬件全局只创建一个驱动实例。</summary>
public ConcurrentDictionary<string, Lazy<IBaseInterface>> HardwarePool { get; set; }
/// <summary>硬件指纹 → 正在使用该设备的作用域名称列表,用于引用计数与安全销毁。</summary>
public ConcurrentDictionary<string, Lazy<List<string>>> DeviceAndScopeDic { get; set; }
public String UserName { get; set; } = "Not Logged in";
public bool IsAdmin { get; set; } = true;
public string CurrentOpeningScope;
@@ -42,6 +45,7 @@ namespace UIShare.GlobalVariable
ConfigDic = new();
ScopeDic = new();
HardwarePool = new ConcurrentDictionary<string, Lazy<IBaseInterface>>(StringComparer.OrdinalIgnoreCase);
DeviceAndScopeDic = new ConcurrentDictionary<string, Lazy<List<string>>>(StringComparer.OrdinalIgnoreCase);
CurrentScope = "default";
}