设备销毁处理
This commit is contained in:
@@ -15,11 +15,12 @@ namespace UIShare.GlobalVariable
|
|||||||
/// 设备管理器:根据 <see cref="SystemConfig.DeviceList"/> 反射实例化所有启用的设备,
|
/// 设备管理器:根据 <see cref="SystemConfig.DeviceList"/> 反射实例化所有启用的设备,
|
||||||
/// 通过 <see cref="IBaseInterface"/> 多态统一管理,避免为每种设备单独硬编码字段。
|
/// 通过 <see cref="IBaseInterface"/> 多态统一管理,避免为每种设备单独硬编码字段。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceManager
|
public class DeviceManager:IDisposable
|
||||||
{
|
{
|
||||||
private object _lockObj = new object();
|
private object _lockObj = new object();
|
||||||
public SystemConfig _systemConfig { get; set; }
|
public SystemConfig _systemConfig { get; set; }
|
||||||
private readonly GlobalInfo _globalInfo;
|
private readonly GlobalInfo _globalInfo;
|
||||||
|
private readonly string _scopeName;
|
||||||
|
|
||||||
/// <summary>按 DeviceName 索引的设备字典,便于业务层按名取实例。</summary>
|
/// <summary>按 DeviceName 索引的设备字典,便于业务层按名取实例。</summary>
|
||||||
public IDictionary<string, IBaseInterface> DeviceMap { get; private set; }
|
public IDictionary<string, IBaseInterface> DeviceMap { get; private set; }
|
||||||
@@ -32,6 +33,8 @@ namespace UIShare.GlobalVariable
|
|||||||
{
|
{
|
||||||
_systemConfig = systemConfig;
|
_systemConfig = systemConfig;
|
||||||
_globalInfo = globalInfo;
|
_globalInfo = globalInfo;
|
||||||
|
// 用 SystemConfig.Title 作为作用域唯一标识,无需反查 ConfigDic
|
||||||
|
_scopeName = _systemConfig.Title;
|
||||||
InitDevices();
|
InitDevices();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -108,6 +111,18 @@ namespace UIShare.GlobalVariable
|
|||||||
DeviceMap[config.DeviceName] = instance;
|
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}");
|
LoggerHelper.Info($"已加载设备 [{config.DeviceName} / {config.DeviceType} / {config.ConnectionType}] 指纹={fingerprint}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -338,6 +353,50 @@ namespace UIShare.GlobalVariable
|
|||||||
};
|
};
|
||||||
return Activator.CreateInstance(type, cfg) as IBaseInterface;
|
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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ namespace UIShare.GlobalVariable
|
|||||||
/// <summary>硬件指纹 → 设备实例的并发池,确保同一物理硬件全局只创建一个驱动实例。</summary>
|
/// <summary>硬件指纹 → 设备实例的并发池,确保同一物理硬件全局只创建一个驱动实例。</summary>
|
||||||
public ConcurrentDictionary<string, Lazy<IBaseInterface>> HardwarePool { get; set; }
|
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 String UserName { get; set; } = "Not Logged in";
|
||||||
public bool IsAdmin { get; set; } = true;
|
public bool IsAdmin { get; set; } = true;
|
||||||
public string CurrentOpeningScope;
|
public string CurrentOpeningScope;
|
||||||
@@ -42,6 +45,7 @@ namespace UIShare.GlobalVariable
|
|||||||
ConfigDic = new();
|
ConfigDic = new();
|
||||||
ScopeDic = new();
|
ScopeDic = new();
|
||||||
HardwarePool = new ConcurrentDictionary<string, Lazy<IBaseInterface>>(StringComparer.OrdinalIgnoreCase);
|
HardwarePool = new ConcurrentDictionary<string, Lazy<IBaseInterface>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
DeviceAndScopeDic = new ConcurrentDictionary<string, Lazy<List<string>>>(StringComparer.OrdinalIgnoreCase);
|
||||||
CurrentScope = "default";
|
CurrentScope = "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user