Axapta 代码在迭代86时崩溃 static void Job47(Args\u Args) { str路径,stx; Treenodeitor iter; TreeNode TreeNode,treeNodeToRelease; 地图显示; FormName FormName; MenuItemName MenuItemName; 容器菜单; inti,n; ; 对于(n=1;n

Axapta 代码在迭代86时崩溃 static void Job47(Args\u Args) { str路径,stx; Treenodeitor iter; TreeNode TreeNode,treeNodeToRelease; 地图显示; FormName FormName; MenuItemName MenuItemName; 容器菜单; inti,n; ; 对于(n=1;n,axapta,x++,Axapta,X++,内核不会立即对TreeNode对象进行垃圾收集。一旦处理完应用程序对象及其所有子对象的TreeNode,您需要调用TreeNode.treeNodeRelease(),然后调用TreeNode=null;,让垃圾收集器进行清理 static void Job47(Args _args) { str path,stx; TreeNodeIterator iter; TreeNode

内核不会立即对TreeNode对象进行垃圾收集。一旦处理完应用程序对象及其所有子对象的TreeNode,您需要调用
TreeNode.treeNodeRelease()
,然后调用
TreeNode=null;
,让垃圾收集器进行清理

static void Job47(Args _args)
 {
 str                                  path,stx;
 TreeNodeIterator                     iter;
 TreeNode                             treeNode, treeNodeToRelease;
 Map                                  dictMenuDisplay;
 FormName                             formName;
 MenuItemName                         menuItemName;
 container                            conMenu;
 int                                  i,n;
   ;

 for (n=1;n<=100;n++)
       {
        info(strfmt("iter:%1",n));
        path            ="Menu Items\\Display";
        dictMenuDisplay = new Map(Types::String,Types::Container);
        treenode        = Treenode::findNode(path);
        iter            = treenode.AOTiterator();
        treenode        = iter.next();

        while (treenode)
          {
          formName     = treenode.AOTgetProperty("Object");
          menuItemName = treenode.AOTname();

           if (dictMenuDisplay.exists(formName))
            {
             conMenu = dictMenuDisplay.lookup(formName);
             conMenu = conIns(conMenu,conlen(conMenu)+1,menuItemName);
             dictMenuDisplay.insert(formName,conMenu);
             }

           else
             dictMenuDisplay.insert(formName,[menuItemName]);
                      //  treenode = iter.next();

           if(treeNodeToRelease && SysTreeNode::isApplObject(treeNode))
            {
             treeNodeToRelease.treeNodeRelease();
             treeNodeToRelease=null;
            }

           if(SysTreeNode::isApplObject(treeNode))
            {
              treeNodeToRelease=treeNode;
            }

            treeNode=iter.next();
        }
    }
  }
守则:

...
TreeNode treeNodeToRelease;
...

while(treenode)
{

    ... /* do stuff with treenode */

    if(treeNodeToRelease && SysTreeNode::isApplObject(treeNode))
    {
        treeNodeToRelease.treeNodeRelease();
        treeNodeToRelease=null;
    }
    if(SysTreeNode::isApplObject(treeNode))
    {
        treeNodeToRelease=treeNode;
    }
    treeNode=iter.next();
}
应替换为:

 if(treeNodeToRelease && SysTreeNode::isApplObject(treeNode))
对象的释放不应依赖于下一个对象

或者这就足够了(取代Jay的解决方案):

引自手册:

如果在同一执行过程中在多个树节点上运行此方法(treeNodeRelease()),则可能会对资源造成要求。您应该在执行过程中卸载树节点,以便垃圾收集器有机会删除它们

在调用此方法之前,请确保删除对树节点及其子节点的所有引用


另外,您至少有85个TreeNodeToRease(和treeNode!)的引用在外部循环的末尾浮动->调用TreeNodeToRease.TreeNodeRease()。

我认为如果您改进发布代码的格式(空行更少,行更短,缩进更好,…)会更容易获得帮助您好,Hofacker先生,在遵循您的建议之后,我对代码进行了修改,您可以在上面的代码中看到。不幸的是,问题仍然存在。请帮助。我正在尝试使用显示菜单项提取所有现有的表单名。为什么要迭代100次?如果您只需要表单列表,您只需要是的,我可以这样做,但我想测试垃圾收集器的使用,比如TreeNode.treeNodeRelease(),TreeNode=null,我想使用它们只是为了知识。我也很想知道现在的代码不起作用,我希望你能理解。(我是AX的新手,非常想了解更多)谢谢Jan的建议,但我在这里看到的是放置treeNode.treeNodeRelease();不会让它遍历整个(3064)节点。它仅限于第一个节点。这取决于下一个对象,因为当您仍在处理应用程序对象的子节点时,不应释放表示该对象的树节点。处理下一个应用程序对象后,您可以释放上一个。谢谢Jay。我按照您的建议和建议应用了更改o编辑了我的代码(你可以看到上面的更改)。我仍然收到错误“内部运行堆栈溢出”,我认为GC与此无关(我不确定,如果我错了,请纠正我)。
 if (treeNodeToRelease)
while (treenode)
{
    ... /* do stuff with treenode */
    treeNode.treeNodeRelease();
    treeNode = iter.next();
}