using Autodesk.Navisworks.Api; using System.Collections.Generic; using System.Threading.Tasks; public static List<ModelItem> GetAllNodes() { List<ModelItem> nodes = new List<ModelItem>(); Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument; // 获取当前文档结构树的根节点 ModelItemCollection rootItems = doc.Models.RootItemDescendants; // 使用多线程遍历根节点下的所有子节点 Parallel.ForEach(rootItems, (rootItem) => { // 将当前节点添加到列表中 lock (nodes) { nodes.Add(rootItem); } // 如果当前节点有子节点,则递归获取所有子节点 if (rootItem.Children.Count > 0) { List<ModelItem> childNodes = GetAllChildNodes(rootItem); lock (nodes) { nodes.AddRange(childNodes); } } }); return nodes; } private static List<ModelItem> GetAllChildNodes(ModelItem parent) { List<ModelItem> childNodes = new List<ModelItem>(); // 使用多线程遍历当前节点的所有子节点 Parallel.ForEach(parent.Children, (child) => { // 将当前节点添加到列表中 lock (childNodes) { childNodes.Add(child); } // 如果当前节点有子节点,则递归获取所有子节点 if (child.Children.Count > 0) { List<ModelItem> grandchildNodes = GetAllChildNodes(child); lock (childNodes) { childNodes.AddRange(grandchildNodes); } } }); return childNodes; } 此代码属于Navisworks 二次开发,获取当前文档结构树全部节点,存储在list<ModelItem>里,要求执行速度要快,优化这段代码。目前代码执行出现数据缺失。
时间: 2024-03-25 22:36:48 浏览: 158
这段代码的多线程实现似乎有一些问题,可能导致数据缺失的情况出现。以下是我对这段代码的优化建议:
1. 将多线程遍历树结构的方法修改为递归遍历,这样可以确保所有节点都能被遍历到,同时避免多线程可能带来的数据竞争问题。
2. 对于递归遍历过程中的每个节点,直接将其添加到列表中,无需使用锁,因为每个节点都是独立的,不存在数据竞争问题。
3. 遍历子节点时,使用 await Task.WhenAll() 方法,将所有子节点的遍历操作异步执行,提高遍历效率。
4. 在递归遍历过程中,使用尾递归优化,避免栈溢出问题。
下面是修改后的代码:
```
using Autodesk.Navisworks.Api;
using System.Collections.Generic;
using System.Threading.Tasks;
public static List<ModelItem> GetAllNodes()
{
List<ModelItem> nodes = new List<ModelItem>();
Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
ModelItemCollection rootItems = doc.Models.RootItemDescendants;
foreach (ModelItem rootItem in rootItems)
{
GetAllChildNodes(rootItem, nodes);
}
return nodes;
}
private static async void GetAllChildNodes(ModelItem parent, List<ModelItem> nodes)
{
nodes.Add(parent);
if (parent.Children.Count > 0)
{
List<Task> tasks = new List<Task>();
foreach (ModelItem child in parent.Children)
{
tasks.Add(Task.Run(() => GetAllChildNodes(child, nodes)));
}
await Task.WhenAll(tasks);
}
}
```
这样优化之后,代码应该可以更快速、准确地获取到文档结构树的全部节点了。
阅读全文