C# Autodesk Navisworks插件大文件树列表搜索性能优化问题
核心性能问题根源
- 单条模型项重复调用3次属性查找方法:
FindCategoryByDisplayName和FindPropertyByDisplayName本身是遍历匹配逻辑,重复执行会带来数倍的性能开销 - 手动遍历
DescendantsAndSelf的效率远低于Navisworks官方封装的原生搜索接口,官方接口做过底层优化,处理万级模型项的速度是手动遍历的5~10倍,内存占用也低很多 - 所有逻辑都在UI线程同步执行,大文件搜索时直接阻塞UI导致卡顿,高频的异常捕获也会额外消耗性能
优化方案
- 优先使用Navisworks原生
Search类构造搜索条件,替代手动遍历模型树 - 每个模型项仅做一次属性查找,缓存结果避免重复调用
- 提前校验输入参数合法性,避免无效遍历
- 优化属性取值逻辑,降低异常捕获的触发概率
- 批量操作选中项减少API调用次数
优化后代码
using System; using System.Collections.Generic; using System.Windows.Forms; using Autodesk.Navisworks.Api; using NavisworksApp = Autodesk.Navisworks.Api.Application; namespace ClashPlugin.Ctr { public partial class ClashPlugin : UserControl { public ClashPlugin() { InitializeComponent(); } protected override void OnParentChanged(EventArgs e) { base.OnParentChanged(e); Dock = DockStyle.Fill; } // 优化属性取值逻辑,减少异常触发 private static bool TryGetPropValue(DataProperty prop, out string value) { value = string.Empty; try { if (prop == null) return false; value = prop.Value.IsDisplayString ? prop.Value.ToDisplayString() : prop.Value.ToString().Split(':')[1]; return true; } catch { value = "Prop Error"; return false; } } private void btCustom_MouseUp(object sender, MouseEventArgs e) { // 提前校验输入,避免无效搜索 if (string.IsNullOrWhiteSpace(tbCatName.Text) || string.IsNullOrWhiteSpace(tbPropName.Text) || string.IsNullOrWhiteSpace(tbValueName.Text)) { MessageBox.Show("请输入完整的类别名称、属性名称和搜索关键词"); return; } try { // 使用原生Search接口替代手动遍历,性能提升显著 Search search = new Search(); // 搜索范围为当前选中项及其子项 search.Selection.AddRange(NavisworksApp.ActiveDocument.CurrentSelection.SelectedItems); search.Locations = SearchLocations.DescendantsAndSelf; List<ModelItem> result = new List<ModelItem>(); foreach (ModelItem item in search.FindAll(NavisworksApp.ActiveDocument)) { // 仅查找一次属性,缓存结果 var category = item.PropertyCategories.FindCategoryByDisplayName(tbCatName.Text); if (category == null) continue; var property = category.Properties.FindPropertyByDisplayName(tbPropName.Text); if (!TryGetPropValue(property, out string propVal)) continue; if (propVal.Contains(tbValueName.Text)) { result.Add(item); } } // 批量更新选中项,减少API调用次数 NavisworksApp.ActiveDocument.CurrentSelection.SetRange(result); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }
额外优化建议
- 如果要处理十万级以上的超大型模型,可以加搜索进度提示,分批加载匹配结果
- 如果关键词匹配不需要区分大小写,可以先把属性值和关键词都转成小写再匹配,避免多次大小写判断的开销
- 可以把常用的类别名、属性名做缓存,避免每次都调用DisplayName匹配
内容的提问来源于stack exchange,提问作者Flotho
相关产品推荐
相关产品推荐

