自动加工脚本程序变量管理器
internal class ProgramVariableCollection : INamedConstantCollection, IEnumerable, IEnumerable { private class SourcePathCompilerHandlePair { private readonly int objectID; private readonly CompilerHandle handle; public int ObjectID => objectID; public CompilerHandle Handle => handle; public SourcePathCompilerHandlePair(int objectID, CompilerHandle handle) { this.objectID = objectID; this.handle = handle; } } private static readonly string[] StackVariableNames = new string[20] { "$O", "$P", "$Q", "$R", "$L", "$I", "$J", "$K", "$stack40", "$stack41", "$stack42", "$stack43", "$stack44", "$stack45", "$stack46", "$stack47", "$stack48", "$stack49", "$stack50", "$stack51" }; private static readonly int NumStackVariables = 32 + StackVariableNames.Length; private readonly Controller controller; private Task task; private SourcePathCompilerHandlePair currentProgram; private readonly List programVariables = new List(); private readonly ReadOnlyCollection stackVariables; private readonly GetValueDelegate getProgramValueDelegate = delegate (Variable v) { double pfdValue_2 = 0.0; ExceptionResolver.ResolveThrow(v.Controller, Wrapper.AerVarProgramGetDouble(v.Controller.Tasks.AllTasks[v.ContextKey].TaskControllerHandle.Value, v.ContextKey, v.Number, ref pfdValue_2)); return pfdValue_2; }; private readonly SetValueDelegate setProgramValueDelegate = delegate (Variable v, object value) { double fdValue_2 = Convert.ToDouble(value); ExceptionResolver.ResolveThrow(v.Controller, Wrapper.AerVarProgramSetDouble(v.Controller.Tasks.AllTasks[v.ContextKey].TaskControllerHandle.Value, v.ContextKey, v.Number, fdValue_2)); }; public TypedVariable this[string name] { get { updateCurrentProgramHandlePair(); if (!name.StartsWith("$")) { name = "$" + name; } return programVariables.Find((TypedVariable progVar) => progVar.Name == name); } } public TypedVariable this[int number] { get { updateCurrentProgramHandlePair(); return programVariables[number]; } } public int Capacity => Count; public int Count { get { updateCurrentProgramHandlePair(); return programVariables.Count; } } internal ProgramVariableCollection(Controller controller, Task task) { this.controller = controller; this.task = task; GetValueDelegate getValueDelegate = delegate (Variable v) { double pfdValue_ = 0.0; ExceptionResolver.ResolveThrow(v.Controller, Wrapper.AerVarStackGetDouble(v.Controller.Tasks.AllTasks[v.ContextKey].TaskControllerHandle.Value, v.ContextKey, v.Number, ref pfdValue_)); return pfdValue_; }; SetValueDelegate setValueDelegate = delegate (Variable v, object value) { double fdValue_ = Convert.ToDouble(value); ExceptionResolver.ResolveThrow(v.Controller, Wrapper.AerVarStackSetDouble(v.Controller.Tasks.AllTasks[v.ContextKey].TaskControllerHandle.Value, v.ContextKey, v.Number, fdValue_)); }; TypedVariable[] array = new TypedVariable[NumStackVariables]; for (int i = 0; i以下是针对 ProgramVariableCollection 类的深度解析与优化建议,结合工业控制编程环境的专业视角:
一、核心功能定位
该类是 数控系统程序变量管理器,主要职责:
-
动态管理:关联任务程序与变量集合
-
双变量空间:
-
程序变量:$var形式的用户定义变量
-
堆栈变量:预定义的$O/$P/$Q等系统变量+32个轴变量
-
编译器集成:通过AerCompiler接口实时解析变量定义
二、架构设计分析
1. 关键组件
组件 类型 作用 currentProgram SourcePathCompilerHandlePair 当前程序的编译器句柄与对象ID缓存 programVariables List 动态程序变量集合(随程序切换变化) stackVariables ReadOnlyCollection 固定堆栈变量(系统预定义+轴变量) getProgramValueDelegate GetValueDelegate 程序变量读操作委托(通过AerVarProgramGetDouble) 2. 变量生命周期管理
三、工业场景优化建议
1. 线程安全增强
private readonly object _syncRoot = new object(); public TypedVariable SafeGetVariable(string name) { lock(_syncRoot) { return this[name]; } }
2. 变量缓存策略
// 添加LRU缓存减少编译器调用 private static readonly ConcurrentDictionary _programCache = new ConcurrentDictionary(); private void populateProgramVariables() { if (_programCache.TryGetValue(currentProgram.ObjectID, out var cachedVars)) { programVariables.AddRange(cachedVars); return; } // ...原有编译逻辑... _programCache.TryAdd(currentProgram.ObjectID, programVariables.ToList()); }
3. 批量操作扩展
public double[] GetVariableRange(int start, int count) { double[] values = new double[count]; for (int i = 0; i
四、关键问题修复
1. 资源泄漏风险
原代码中编译器句柄可能未释放:
// 添加析构函数确保释放 ~ProgramVariableCollection() { currentProgram?.Handle.Dispose(); }
2. 数组越界隐患
stackVariables初始化时硬编码长度检查:
// 改为动态校验 if (array.Length != NumStackVariables) throw new InvalidOperationException("Stack variables count mismatch");
3. 变量名解析缺陷
特殊字符处理不足:
// 在updateCurrentProgramHandlePair()中添加 name = Regex.Replace(name, @"[^\w$]", ""); // 移除非单词字符
五、性能优化方案
1. 预编译变量索引
private Dictionary _varNameIndex; private void BuildNameIndex() { _varNameIndex = programVariables .Select((v, i) => new { v.Name, i }) .ToDictionary(x => x.Name, x => x.i); }
2. 委托调用优化
// 使用Calli指令替换委托调用(需unsafe) private static readonly delegate* unmanaged _getProgramVarFunc = &Wrapper.AerVarProgramGetDouble;
3. 内存池技术
private static readonly ArrayPool _valuePool = ArrayPool.Shared; double[] tempArray = _valuePool.Rent(count); try { // 使用tempArray操作 } finally { _valuePool.Return(tempArray); }
六、典型应用场景
1. G代码变量监控
// 监控程序中的#100变量 var var100 = programVars["$100"]; double currentValue = var100.Value;
2. 刀具补偿管理
// 批量读取刀具半径补偿 double[] toolComp = programVars .Where(v => v.Name.StartsWith("$TC_")) .Select(v => v.Value) .ToArray();
3. 程序调试支持
// 获取当前程序所有变量快照 var snapshot = programVars .ToDictionary(v => v.Name, v => v.Value);
七、扩展性设计
1. 变量变更事件
public event EventHandler VariableChanged; // 在setProgramValueDelegate中触发事件
2. 多语言支持
public string GetLocalizedVarName(string rawName) { return _resourceManager.GetString($"VAR_{rawName.TrimStart('$')}"); }
3. 硬件加速
[MethodImpl(MethodImplOptions.AggressiveInlining)] public double GetValueOptimized(int index) => this[index].Value;
该设计优化后可在数控系统、机器人控制器等实时环境中稳定运行,满足以下工业要求:
-
实时性:变量访问延迟
-
-
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。