Axapta 代码在迭代86时崩溃 static void Job47(Args\u Args) { str路径,stx; Treenodeitor iter; TreeNode TreeNode,treeNodeToRelease; 地图显示; FormName FormName; MenuItemName MenuItemName; 容器菜单; inti,n; ; 对于(n=1;n
内核不会立即对TreeNode对象进行垃圾收集。一旦处理完应用程序对象及其所有子对象的TreeNode,您需要调用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.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();
}