NavisworksTransport/doc/guide/crash_fix_summary.md

6.3 KiB
Raw Permalink Blame History

分层拆分崩溃问题修复总结

🔍 问题诊断结果

通过详细的日志分析,我们精确定位了崩溃的根本原因:

崩溃位置

[INFO] [ModelSplitter] 重置所有隐藏状态...

程序在执行 document.Models.ResetAllHidden() 时崩溃,没有后续的"重置完成"日志。

根本原因

ResetAllHidden() API在某些情况下会导致Navisworks程序崩溃特别是

  • 处理大型模型时
  • 模型结构复杂时
  • 内存使用较高时
  • 某些特定的模型文件格式

🛠️ 关键修复措施

1. ModelSplitterManager.cs 修复

A. EnsureStableState() 方法

修复前(崩溃代码)

document.Models.ResetAllHidden(); // 导致崩溃

修复后(安全代码)

// 完全跳过可见性重置,避免崩溃风险
LogManager.Info("[ModelSplitter] 跳过可见性重置以避免崩溃风险");
LogManager.Info("[ModelSplitter] 使用选择集策略替代可见性控制");

// 只进行安全的操作
document.CurrentSelection.Clear(); // 这是安全的

B. RecoverFromError() 方法

修复前

document.Models.ResetAllHidden(); // 可能导致二次崩溃

修复后

try
{
    document.Models.ResetAllHidden();
    LogManager.Info("[ModelSplitter] 错误恢复ResetAllHidden成功");
}
catch (Exception resetEx)
{
    LogManager.Warning($"[ModelSplitter] 错误恢复ResetAllHidden失败: {resetEx.Message}");
    LogManager.Info("[ModelSplitter] 错误恢复:跳过可见性重置");
}

C. FinalCleanup() 方法

修复后

try
{
    document.Models.ResetAllHidden();
    LogManager.Info("[ModelSplitter] 最终清理ResetAllHidden成功");
}
catch (Exception resetEx)
{
    LogManager.Warning($"[ModelSplitter] 最终清理ResetAllHidden失败: {resetEx.Message}");
    LogManager.Info("[ModelSplitter] 最终清理:跳过可见性重置");
}

2. NavisworksFileExporter.cs 修复

A. ExportByVisibilityControlAsync() 方法

修复前(崩溃代码)

// 首先重置所有隐藏状态,确保从干净状态开始
document.Models.ResetAllHidden(); // 导致崩溃

修复后(安全代码)

// 关键修复完全避免使用ResetAllHidden改用选择集策略
LogManager.Info("[FileExporter] 使用选择集策略替代可见性控制");

// 不再使用可见性控制,直接使用选择集方法
OnStatusChanged("正在设置选择集...");

// 清除当前选择
document.CurrentSelection.Clear();

// 设置要导出的元素为选中状态
document.CurrentSelection.AddRange(items);

B. 可见性恢复修复

修复前

document.Models.ResetAllHidden(); // 可能导致崩溃

修复后

// 只显示之前隐藏的元素,而不是重置所有
if (itemsToHide.Count > 0)
{
    document.Models.SetHidden(itemsToHide, false);
    LogManager.Info($"[FileExporter] 已恢复 {itemsToHide.Count} 个元素的可见性");
}

C. 异常处理修复

修复前

document.Models.ResetAllHidden(); // 异常处理中可能导致二次崩溃

修复后

// 关键修复避免在异常处理中使用ResetAllHidden
LogManager.Error($"[FileExporter] 导出过程中发生异常: {ex.Message}");
LogManager.Info("[FileExporter] 跳过异常恢复中的可见性重置,避免二次崩溃");

// 只进行安全的清理操作
try
{
    // 清除选择集是安全的
    document.CurrentSelection.Clear();
    LogManager.Info("[FileExporter] 异常恢复:已清除选择集");
}
catch (Exception safeEx)
{
    LogManager.Warning($"[FileExporter] 异常恢复中的安全操作也失败: {safeEx.Message}");
}

🔄 新的工作策略

替代方案1选择集策略

  • 不再使用可见性控制
  • 改用选择集来标识要导出的元素
  • 通过 document.CurrentSelection.AddRange(items) 设置选择

替代方案2安全的可见性操作

  • 只使用 SetHidden(collection, true/false) 进行局部控制
  • 避免使用 ResetAllHidden() 进行全局重置
  • 只恢复之前隐藏的特定元素

替代方案3错误容忍机制

  • 所有可见性操作都包装在 try-catch 中
  • 失败时记录日志但继续处理
  • 提供多种备用策略

📊 修复效果预期

稳定性提升

  • 崩溃率: 从高频崩溃降至几乎为零
  • 错误恢复: 即使部分操作失败,程序也能继续运行
  • 内存管理: 避免了大量可见性操作导致的内存问题

性能优化

  • 处理速度: 减少了不必要的全局可见性重置
  • 资源使用: 降低了内存和CPU使用
  • 响应性: 减少了UI阻塞时间

用户体验改善

  • 可靠性: 分层拆分功能更加稳定
  • 反馈: 详细的日志记录便于问题诊断
  • 容错性: 部分失败不会影响整体操作

🧪 测试建议

测试步骤

  1. 小型模型测试

    • 使用简单的模型文件
    • 验证基本分层功能
    • 检查日志记录是否正常
  2. 中型模型测试

    • 使用包含多个楼层的模型
    • 测试不同的分层策略
    • 观察内存使用情况
  3. 大型模型测试

    • 使用复杂的建筑模型
    • 分批处理每批3-5个分层
    • 监控系统稳定性

监控要点

  • 查看日志中是否还有 ResetAllHidden 相关的崩溃
  • 观察内存使用是否稳定
  • 检查文件导出是否成功
  • 验证可见性恢复是否正常

🚨 如果仍然出现问题

日志关键词搜索

NavisworksTransport_Debug.log 中搜索:

  • ERROR - 查找错误信息
  • 异常 - 查找异常情况
  • 崩溃 - 查找崩溃相关信息
  • ResetAllHidden - 检查是否还有遗漏的调用

备用策略

如果问题仍然存在,可以考虑:

  1. 完全禁用可见性控制:只使用选择集策略
  2. 分批处理每次只处理1个分层
  3. 重启策略每处理几个分层后重启Navisworks

📝 更新记录

  • v1.2 (2025-07-16): 修复 ResetAllHidden() 崩溃问题
  • v1.1 (2025-07-16): 增强日志记录和错误处理
  • v1.0 (2025-07-16): 初始版本

现在请重新测试分层拆分功能!

根据日志分析,崩溃问题应该已经完全解决。如果仍有问题,请立即查看最新的日志文件并提供相关信息。