自动加工脚本程序变量管理器

06-02 1252阅读
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. 关键组件
      组件类型作用
      currentProgramSourcePathCompilerHandlePair当前程序的编译器句柄与对象ID缓存
      programVariablesList动态程序变量集合(随程序切换变化)
      stackVariablesReadOnlyCollection固定堆栈变量(系统预定义+轴变量)
      getProgramValueDelegateGetValueDelegate程序变量读操作委托(通过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,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码