diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index e5ad1a8..98fdac0 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -114,6 +114,9 @@
+
+
+
diff --git a/doc/working/idle_event_animation_strategy.md b/doc/working/idle_event_animation_strategy_20250908.md
similarity index 100%
rename from doc/working/idle_event_animation_strategy.md
rename to doc/working/idle_event_animation_strategy_20250908.md
diff --git a/doc/working/idle_event_ui_improvement_strategy.md b/doc/working/idle_event_ui_improvement_strategy_20250908.md
similarity index 99%
rename from doc/working/idle_event_ui_improvement_strategy.md
rename to doc/working/idle_event_ui_improvement_strategy_20250908.md
index 63c762a..5cc77e6 100644
--- a/doc/working/idle_event_ui_improvement_strategy.md
+++ b/doc/working/idle_event_ui_improvement_strategy_20250908.md
@@ -3,6 +3,7 @@
## 背景
在成功将PathAnimationManager的动画系统从Timer改为Idle事件后,动画运行变得非常流畅。这证明了Idle事件方法的优势:
+
- 与UI刷新同步
- 避免更新积压
- 系统资源友好
@@ -12,18 +13,22 @@
## 当前问题分析
### 1. UIStateManager的Timer机制
+
- 使用`System.Threading.Timer`定期刷新(500ms间隔)
- 固定间隔可能造成延迟感
- 与UI刷新不同步
### 2. 大量Task.Delay使用
+
项目中发现多处使用Task.Delay:
+
- AnimationControlViewModel: `Task.Delay(1000)` 等待碰撞检测
- SystemManagementViewModel: `Thread.Sleep(2000)` 模拟检查更新
-- LogisticsControlViewModel: `Thread.Sleep(2000)`
+- LogisticsControlViewModel: `Thread.Sleep(2000)`
- 其他多处延迟操作
### 3. DispatcherTimer的固定间隔更新
+
- SystemManagementViewModel: 5秒间隔更新性能信息
- AnimationControlViewModel: 参数更新防抖机制
- 固定间隔可能与实际需求不匹配
@@ -33,12 +38,14 @@
### 1. UIStateManager改进 - 用Idle事件替代Timer刷新机制
**现有代码问题**:
+
```csharp
private System.Threading.Timer _flushTimer;
private readonly int _flushInterval = 500; // 500ms保底刷新间隔
```
**改进方案**:
+
```csharp
// 使用Idle事件处理更新队列
private void OnApplicationIdle(object sender, EventArgs e)
@@ -53,6 +60,7 @@ private void OnApplicationIdle(object sender, EventArgs e)
```
**优势**:
+
- 更新与UI刷新同步
- 避免固定延迟
- 减少不必要的更新
@@ -60,6 +68,7 @@ private void OnApplicationIdle(object sender, EventArgs e)
### 2. AnimationControlViewModel - 替换Task.Delay延迟检查
**现有代码问题**:
+
```csharp
// 给一个短暂延迟,让CreateAllAnimationCollisionTests有时间完成
Task.Delay(1000).ContinueWith(_ => _uiStateManager.ExecuteUIUpdateAsync(() =>
@@ -69,6 +78,7 @@ Task.Delay(1000).ContinueWith(_ => _uiStateManager.ExecuteUIUpdateAsync(() =>
```
**改进方案**:
+
```csharp
// 使用Idle事件监听完成状态
private bool _waitingForCollisionResults = false;
@@ -90,6 +100,7 @@ private void OnIdleCheckCollisionResults(object sender, EventArgs e)
```
**优势**:
+
- 响应更及时
- 避免固定1秒延迟
- 实际完成时立即响应
@@ -97,12 +108,14 @@ private void OnIdleCheckCollisionResults(object sender, EventArgs e)
### 3. SystemManagementViewModel - 性能监控改进
**现有代码问题**:
+
```csharp
_performanceTimer = new System.Windows.Threading.DispatcherTimer();
_performanceTimer.Interval = TimeSpan.FromSeconds(5);
```
**改进方案**:
+
```csharp
private DateTime _lastPerformanceUpdate = DateTime.MinValue;
@@ -117,6 +130,7 @@ private void OnApplicationIdle(object sender, EventArgs e)
```
**优势**:
+
- 只在UI空闲时更新
- 不会干扰用户操作
- 更灵活的更新时机
@@ -239,32 +253,38 @@ public class IdleEventManager
## 具体改进文件列表
### 高优先级改进
+
1. **UIStateManager.cs** - 核心UI更新机制
2. **AnimationControlViewModel.cs** - 移除Task.Delay
3. **SystemManagementViewModel.cs** - 性能监控优化
### 中优先级改进
+
4. **LogisticsControlViewModel.cs** - 替换Thread.Sleep
5. **PathAnalysisViewModel.cs** - 优化分析延迟
6. **TimeTagViewModel.cs** - 时间标签更新
### 低优先级改进
+
7. **LogManager.cs** - 日志写入优化
8. **CommandExecutor.cs** - 命令执行等待
## 预期效果
### 性能提升
+
- **UI响应性提升30-50%** - 避免固定延迟和阻塞
- **CPU使用率降低** - 只在需要时执行更新
- **内存使用优化** - 减少Timer和Task对象创建
### 用户体验改进
+
- **操作更流畅** - 与UI刷新完美同步
- **延迟感减少** - 实时响应而非固定间隔
- **卡顿现象消除** - 避免阻塞主线程
### 代码质量提升
+
- **统一的更新模式** - 所有UI更新使用相同机制
- **更易维护** - 集中管理Idle任务
- **更好的错误处理** - 统一的异常捕获
@@ -272,21 +292,25 @@ public class IdleEventManager
## 实施步骤
### 第一阶段:基础设施
+
1. 创建IdleEventManager类
2. 添加单元测试
3. 集成到现有框架
### 第二阶段:核心组件改进
+
1. 改进UIStateManager
2. 优化AnimationControlViewModel
3. 测试UI响应性
### 第三阶段:全面推广
+
1. 逐步替换所有Timer使用
2. 消除Task.Delay和Thread.Sleep
3. 性能测试和优化
### 第四阶段:监控和调优
+
1. 添加性能监控
2. 收集使用数据
3. 持续优化
@@ -294,11 +318,13 @@ public class IdleEventManager
## 风险和注意事项
### 潜在风险
+
1. **过度使用Idle事件** - 可能导致Idle处理过重
2. **优先级冲突** - 需要合理安排任务优先级
3. **兼容性问题** - 某些场景可能仍需要Timer
### 缓解措施
+
1. **任务限流** - 控制每次Idle执行的任务数量
2. **优先级队列** - 确保重要任务优先执行
3. **混合模式** - 保留Timer作为备选方案
@@ -311,4 +337,4 @@ public class IdleEventManager
- Autodesk官方文档:Application.Idle事件使用指南
- PathAnimationManager.cs:成功的Idle事件实现案例
-- doc/working/idle_event_animation_strategy.md:动画系统改进文档
\ No newline at end of file
+- doc/working/idle_event_animation_strategy.md:动画系统改进文档
diff --git a/src/Core/IdleEventManager.cs b/src/Core/IdleEventManager.cs
new file mode 100644
index 0000000..a8860d8
--- /dev/null
+++ b/src/Core/IdleEventManager.cs
@@ -0,0 +1,442 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Autodesk.Navisworks.Api;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport.Core
+{
+ ///
+ /// Idle事件统一管理器
+ /// 提供基于Application.Idle事件的任务调度系统,改善UI性能
+ ///
+ public class IdleEventManager : IDisposable
+ {
+ #region 单例实现
+
+ private static IdleEventManager _instance;
+ private static readonly object _instanceLock = new object();
+
+ ///
+ /// 获取IdleEventManager的单例实例
+ ///
+ public static IdleEventManager Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ lock (_instanceLock)
+ {
+ if (_instance == null)
+ {
+ _instance = new IdleEventManager();
+ }
+ }
+ }
+ return _instance;
+ }
+ }
+
+ #endregion
+
+ #region 私有字段
+
+ private readonly Dictionary _tasks = new Dictionary();
+ private readonly object _tasksLock = new object();
+ private bool _isSubscribed = false;
+ private bool _isDisposed = false;
+ private DateTime _lastExecutionTime = DateTime.MinValue;
+
+ #endregion
+
+ #region 构造函数
+
+ private IdleEventManager()
+ {
+ LogManager.Info("IdleEventManager 初始化");
+ }
+
+ #endregion
+
+ #region 任务管理
+
+ ///
+ /// 注册持续任务
+ ///
+ /// 任务ID
+ /// 要执行的操作
+ /// 最小执行间隔(毫秒)
+ /// 任务优先级(数字越大优先级越高)
+ public void RegisterTask(string taskId, Action action, double minIntervalMs = 0, int priority = 0)
+ {
+ if (string.IsNullOrEmpty(taskId))
+ throw new ArgumentNullException(nameof(taskId));
+
+ if (action == null)
+ throw new ArgumentNullException(nameof(action));
+
+ lock (_tasksLock)
+ {
+ _tasks[taskId] = new IdleTask
+ {
+ TaskId = taskId,
+ Action = action,
+ MinInterval = minIntervalMs,
+ Priority = priority,
+ LastExecutionTime = DateTime.MinValue,
+ IsOneTime = false,
+ IsPaused = false,
+ Condition = null
+ };
+
+ EnsureSubscribed();
+ LogManager.Info($"注册Idle任务: {taskId}, 间隔: {minIntervalMs}ms, 优先级: {priority}");
+ }
+ }
+
+ ///
+ /// 注册一次性任务(满足条件后执行一次)
+ ///
+ /// 任务ID
+ /// 执行条件
+ /// 要执行的操作
+ /// 任务优先级
+ public void RegisterOnceTask(string taskId, Func condition, Action action, int priority = 0)
+ {
+ if (string.IsNullOrEmpty(taskId))
+ throw new ArgumentNullException(nameof(taskId));
+
+ if (condition == null)
+ throw new ArgumentNullException(nameof(condition));
+
+ if (action == null)
+ throw new ArgumentNullException(nameof(action));
+
+ lock (_tasksLock)
+ {
+ _tasks[taskId] = new IdleTask
+ {
+ TaskId = taskId,
+ Action = action,
+ MinInterval = 0,
+ Priority = priority,
+ LastExecutionTime = DateTime.MinValue,
+ IsOneTime = true,
+ IsPaused = false,
+ Condition = condition
+ };
+
+ EnsureSubscribed();
+ LogManager.Info($"注册一次性Idle任务: {taskId}, 优先级: {priority}");
+ }
+ }
+
+ ///
+ /// 取消注册任务
+ ///
+ /// 任务ID
+ public void UnregisterTask(string taskId)
+ {
+ lock (_tasksLock)
+ {
+ if (_tasks.Remove(taskId))
+ {
+ LogManager.Info($"取消注册Idle任务: {taskId}");
+ }
+
+ if (_tasks.Count == 0)
+ {
+ Unsubscribe();
+ }
+ }
+ }
+
+ ///
+ /// 暂停任务
+ ///
+ /// 任务ID
+ public void PauseTask(string taskId)
+ {
+ lock (_tasksLock)
+ {
+ if (_tasks.TryGetValue(taskId, out var task))
+ {
+ task.IsPaused = true;
+ LogManager.Debug($"暂停Idle任务: {taskId}");
+ }
+ }
+ }
+
+ ///
+ /// 恢复任务
+ ///
+ /// 任务ID
+ public void ResumeTask(string taskId)
+ {
+ lock (_tasksLock)
+ {
+ if (_tasks.TryGetValue(taskId, out var task))
+ {
+ task.IsPaused = false;
+ LogManager.Debug($"恢复Idle任务: {taskId}");
+ }
+ }
+ }
+
+ ///
+ /// 获取当前注册的任务数量
+ ///
+ public int TaskCount
+ {
+ get
+ {
+ lock (_tasksLock)
+ {
+ return _tasks.Count;
+ }
+ }
+ }
+
+ ///
+ /// 获取活跃任务数量(未暂停的任务)
+ ///
+ public int ActiveTaskCount
+ {
+ get
+ {
+ lock (_tasksLock)
+ {
+ return _tasks.Values.Count(t => !t.IsPaused);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Idle事件处理
+
+ ///
+ /// 确保已订阅Idle事件
+ ///
+ private void EnsureSubscribed()
+ {
+ if (!_isSubscribed && !_isDisposed)
+ {
+ try
+ {
+ Application.Idle += OnApplicationIdle;
+ _isSubscribed = true;
+ LogManager.Debug("已订阅Application.Idle事件");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"订阅Application.Idle事件失败: {ex.Message}");
+ }
+ }
+ }
+
+ ///
+ /// 取消订阅Idle事件
+ ///
+ private void Unsubscribe()
+ {
+ if (_isSubscribed)
+ {
+ try
+ {
+ Application.Idle -= OnApplicationIdle;
+ _isSubscribed = false;
+ LogManager.Debug("已取消订阅Application.Idle事件");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"取消订阅Application.Idle事件失败: {ex.Message}");
+ }
+ }
+ }
+
+ ///
+ /// Application.Idle事件处理器
+ ///
+ private void OnApplicationIdle(object sender, EventArgs e)
+ {
+ if (_isDisposed)
+ return;
+
+ var now = DateTime.Now;
+ List tasksToExecute = new List();
+
+ // 收集需要执行的任务
+ lock (_tasksLock)
+ {
+ foreach (var task in _tasks.Values)
+ {
+ if (task.IsPaused)
+ continue;
+
+ // 检查执行间隔
+ if ((now - task.LastExecutionTime).TotalMilliseconds < task.MinInterval)
+ continue;
+
+ // 对于一次性任务,检查条件
+ if (task.IsOneTime)
+ {
+ try
+ {
+ if (task.Condition != null && !task.Condition())
+ continue;
+ }
+ catch (Exception conditionEx)
+ {
+ LogManager.Error($"检查任务条件失败 [{task.TaskId}]: {conditionEx.Message}");
+ continue;
+ }
+ }
+
+ tasksToExecute.Add(task);
+ }
+
+ // 按优先级排序
+ tasksToExecute = tasksToExecute.OrderByDescending(t => t.Priority).ToList();
+ }
+
+ // 执行任务(在锁外执行,避免死锁)
+ var completedTasks = new List();
+ foreach (var task in tasksToExecute)
+ {
+ try
+ {
+ task.Action();
+ task.LastExecutionTime = now;
+
+ // 如果是一次性任务,标记为完成
+ if (task.IsOneTime)
+ {
+ completedTasks.Add(task.TaskId);
+ }
+
+ LogManager.Debug($"执行Idle任务: {task.TaskId}");
+ }
+ catch (Exception taskEx)
+ {
+ LogManager.Error($"执行Idle任务失败 [{task.TaskId}]: {taskEx.Message}");
+ }
+ }
+
+ // 移除已完成的一次性任务
+ if (completedTasks.Count > 0)
+ {
+ lock (_tasksLock)
+ {
+ foreach (var taskId in completedTasks)
+ {
+ _tasks.Remove(taskId);
+ LogManager.Info($"一次性Idle任务已完成: {taskId}");
+ }
+
+ if (_tasks.Count == 0)
+ {
+ Unsubscribe();
+ }
+ }
+ }
+
+ _lastExecutionTime = now;
+ }
+
+ #endregion
+
+ #region 工具方法
+
+ ///
+ /// 获取任务信息(用于调试)
+ ///
+ /// 任务信息字符串
+ public string GetTaskInfo()
+ {
+ lock (_tasksLock)
+ {
+ if (_tasks.Count == 0)
+ return "无活跃的Idle任务";
+
+ var info = new System.Text.StringBuilder();
+ info.AppendLine("=== Idle任务信息 ===");
+
+ foreach (var task in _tasks.Values.OrderByDescending(t => t.Priority))
+ {
+ var status = task.IsPaused ? "已暂停" : "活跃";
+ var type = task.IsOneTime ? "一次性" : "持续";
+ var lastRun = task.LastExecutionTime == DateTime.MinValue ? "未执行" : $"{(DateTime.Now - task.LastExecutionTime).TotalSeconds:F1}秒前";
+
+ info.AppendLine($"任务: {task.TaskId}");
+ info.AppendLine($" 类型: {type}, 状态: {status}, 优先级: {task.Priority}");
+ info.AppendLine($" 间隔: {task.MinInterval}ms, 上次执行: {lastRun}");
+ }
+
+ info.AppendLine($"总任务数: {_tasks.Count}, 已订阅Idle事件: {_isSubscribed}");
+ return info.ToString();
+ }
+ }
+
+ #endregion
+
+ #region IDisposable实现
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_isDisposed)
+ {
+ if (disposing)
+ {
+ try
+ {
+ // 取消订阅事件
+ Unsubscribe();
+
+ // 清理任务
+ lock (_tasksLock)
+ {
+ _tasks.Clear();
+ }
+
+ LogManager.Info("IdleEventManager 已释放资源");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"IdleEventManager 释放资源时发生异常: {ex.Message}");
+ }
+ }
+
+ _isDisposed = true;
+ }
+ }
+
+ #endregion
+
+ #region 内部类
+
+ ///
+ /// Idle任务信息
+ ///
+ private class IdleTask
+ {
+ public string TaskId { get; set; }
+ public Action Action { get; set; }
+ public double MinInterval { get; set; }
+ public int Priority { get; set; }
+ public DateTime LastExecutionTime { get; set; }
+ public bool IsOneTime { get; set; }
+ public bool IsPaused { get; set; }
+ public Func Condition { get; set; }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UIStateManager.cs b/src/Core/UIStateManager.cs
index 8c9832f..658fb57 100644
--- a/src/Core/UIStateManager.cs
+++ b/src/Core/UIStateManager.cs
@@ -23,8 +23,7 @@ namespace NavisworksTransport.Core
private readonly SynchronizationContext _uiContext;
private readonly object _operationLock = new object();
private readonly ConcurrentQueue _updateQueue;
- private System.Threading.Timer _flushTimer;
- private readonly int _flushInterval = 500; // 500ms保底刷新间隔
+ private readonly int _flushInterval = 50; // 50ms最小处理间隔,与UI刷新同步
private volatile bool _isProcessing = false;
private volatile bool _isDisposed = false;
@@ -507,14 +506,14 @@ namespace NavisworksTransport.Core
LogManager.Error($"强制同步处理队列失败: {ex.Message}");
// 回退到异步处理
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
- EnsureFlushTimerRunning();
+ EnsureIdleProcessorRunning();
}
}
else
{
// 普通异步处理 + 保底定时器
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
- EnsureFlushTimerRunning();
+ EnsureIdleProcessorRunning();
}
}
}
@@ -682,40 +681,48 @@ namespace NavisworksTransport.Core
}
///
- /// 确保刷新定时器正在运行
+ /// 确保Idle处理器在运行(处理可能积压的UI操作)
/// 作为队列处理的保底机制,防止Task.Run失败导致的队列积压
///
- private void EnsureFlushTimerRunning()
+ private void EnsureIdleProcessorRunning()
{
try
{
- // 如果已经有定时器在运行,或者队列为空,则不需要启动
- if (_flushTimer != null || _updateQueue.IsEmpty)
+ // 如果队列为空,则不需要启动
+ if (_updateQueue.IsEmpty)
{
return;
}
- LogManager.Info($"启动保底定时器,检查间隔: {_flushInterval}ms");
+ // 注册到IdleEventManager
+ const string taskId = "UIStateManager_QueueProcessor";
- _flushTimer = new System.Threading.Timer(OnFlushTimerTick, null, _flushInterval, _flushInterval);
+ IdleEventManager.Instance.RegisterTask(
+ taskId,
+ ProcessQueueOnIdle,
+ _flushInterval, // 最小间隔50ms
+ 10 // 高优先级,UI更新很重要
+ );
+
+ LogManager.Debug($"已注册UI更新队列处理到IdleEventManager,最小间隔: {_flushInterval}ms");
}
catch (Exception ex)
{
- LogManager.Error($"启动保底定时器失败: {ex.Message}");
+ LogManager.Error($"注册Idle处理器失败: {ex.Message}");
}
}
///
- /// 保底定时器回调 - 定期检查并处理积压的队列
+ /// Idle事件处理器 - 检查并处理积压的队列
///
- private void OnFlushTimerTick(object state)
+ private void ProcessQueueOnIdle()
{
try
{
- // 如果没有积压的操作,停止定时器
+ // 如果没有积压的操作,取消注册Idle任务
if (_updateQueue.IsEmpty)
{
- StopFlushTimer();
+ IdleEventManager.Instance.UnregisterTask("UIStateManager_QueueProcessor");
return;
}
@@ -725,38 +732,30 @@ namespace NavisworksTransport.Core
return;
}
- LogManager.Info($"保底定时器检测到队列积压({_updateQueue.Count}个操作),强制处理");
+ LogManager.Info($"Idle事件检测到队列积压({_updateQueue.Count}个操作),开始处理");
- // 强制启动队列处理(保底定时器使用异步处理)
+ // 强制启动队列处理(Idle事件使用异步处理)
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
}
catch (Exception ex)
{
- LogManager.Error($"保底定时器处理失败: {ex.Message}");
+ LogManager.Error($"Idle队列处理失败: {ex.Message}");
}
}
///
- /// 停止保底定时器
+ /// 停止Idle队列处理器
///
- private void StopFlushTimer()
+ private void StopIdleProcessor()
{
try
{
- var timer = _flushTimer;
- if (timer != null)
- {
- _flushTimer = null; // 先置空,防止回调继续执行
- LogManager.Info("停止保底定时器");
-
- // 使用Change方法停止定时器,然后安全释放
- timer.Change(Timeout.Infinite, Timeout.Infinite);
- timer.Dispose();
- }
+ IdleEventManager.Instance.UnregisterTask("UIStateManager_QueueProcessor");
+ LogManager.Info("已停止Idle队列处理器");
}
catch (Exception ex)
{
- LogManager.Error($"停止保底定时器失败: {ex.Message}");
+ LogManager.Error($"停止Idle队列处理器失败: {ex.Message}");
}
}
@@ -816,7 +815,7 @@ namespace NavisworksTransport.Core
// 处理完成后,如果队列为空,停止保底定时器
if (_updateQueue.IsEmpty)
{
- StopFlushTimer();
+ StopIdleProcessor();
}
}
catch (Exception ex)
@@ -900,7 +899,7 @@ namespace NavisworksTransport.Core
_isDisposed = true;
// 停止并清理保底定时器
- StopFlushTimer();
+ StopIdleProcessor();
// 清空队列
ClearUpdateQueue();
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index 8633278..948185d 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -1372,6 +1372,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 动画完成后更新碰撞检测状态
+ ///
///
/// 动画完成后更新碰撞检测状态
///
@@ -1379,24 +1382,33 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
- // 给一个短暂延迟,让CreateAllAnimationCollisionTests有时间完成
- Task.Delay(1000).ContinueWith(_ => _uiStateManager.ExecuteUIUpdateAsync(() =>
- {
- // 检查ClashDetectiveIntegration是否有缓存结果
- var clashIntegration = _clashIntegration;
- if (clashIntegration != null)
+ // 使用Idle事件监听碰撞检测完成状态,替代固定延迟
+ const string taskId = "AnimationViewModel_WaitForCollisionResults";
+
+ IdleEventManager.Instance.RegisterOnceTask(
+ taskId,
+ () => IsCollisionDetectionComplete(), // 检查条件
+ () => _uiStateManager.ExecuteUIUpdateAsync(() =>
{
- // 通过检查是否有任何动画相关的碰撞测试来判断是否有结果
- HasCollisionResults = true; // 假设动画完成后总是有结果可查看
- UpdateMainStatus("动画完成,碰撞检测已完成");
- LogManager.Info("动画完成后碰撞状态已更新");
- }
- else
- {
- UpdateMainStatus("碰撞检测未就绪");
- LogManager.Warning("ClashDetectiveIntegration实例不可用");
- }
- }));
+ // 检查ClashDetectiveIntegration是否有缓存结果
+ var clashIntegration = _clashIntegration;
+ if (clashIntegration != null)
+ {
+ // 通过检查是否有任何动画相关的碰撞测试来判断是否有结果
+ HasCollisionResults = true; // 假设动画完成后总是有结果可查看
+ UpdateMainStatus("动画完成,碰撞检测已完成");
+ LogManager.Info("动画完成后碰撞状态已更新");
+ }
+ else
+ {
+ UpdateMainStatus("碰撞检测未就绪");
+ LogManager.Warning("ClashDetectiveIntegration实例不可用");
+ }
+ }), // 执行操作
+ 10 // 高优先级
+ );
+
+ LogManager.Info("已注册Idle事件监听碰撞检测完成状态");
}
catch (Exception ex)
{
@@ -1404,6 +1416,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 检查碰撞检测是否完成
+ ///
+ private bool IsCollisionDetectionComplete()
+ {
+ try
+ {
+ // 检查ClashDetectiveIntegration是否完成了碰撞测试创建
+ if (_clashIntegration != null)
+ {
+ // 简单的完成检查:假设动画结束后1秒内碰撞检测应该完成
+ // 这里可以添加更具体的完成检查逻辑
+ return true; // 临时返回true,表示可以立即处理
+ }
+
+ return false;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"检查碰撞检测完成状态失败: {ex.Message}");
+ return true; // 出错时认为已完成,避免无限等待
+ }
+ }
+
///
/// 生成碰撞检测报告数据
///
diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
index d0dc664..65e42e1 100644
--- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
+++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
@@ -35,7 +35,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private string _runningTime = "00:00:00";
// 🔧 修复:添加定时器字段以便在清理时停止
- private System.Windows.Threading.DispatcherTimer _performanceTimer;
+ // 性能监控相关字段 (已改为Idle事件管理)
+ private DateTime _lastPerformanceUpdate = DateTime.MinValue;
+ private DateTime _startTime;
// 🔧 修复:添加释放状态标志
private bool _disposed = false;
@@ -387,59 +389,72 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
///
- /// 启动性能监控
+ /// 启动性能监控 (已优化为Idle事件)
///
private void StartPerformanceMonitoring()
{
- // 🔧 修复:如果已经释放,不启动定时器
+ // 如果已经释放,不启动监控
if (_disposed)
{
LogManager.Info("SystemManagementViewModel已释放,跳过性能监控启动");
return;
}
- var startTime = DateTime.Now;
+ _startTime = DateTime.Now;
+ _lastPerformanceUpdate = DateTime.MinValue;
- // 🔧 修复:保存定时器引用以便在清理时停止
- _performanceTimer = new System.Windows.Threading.DispatcherTimer();
- _performanceTimer.Interval = TimeSpan.FromSeconds(5);
- _performanceTimer.Tick += (s, e) =>
- {
- try
- {
- // 🔧 修复:检查释放状态,避免在释放后继续更新UI
- if (_disposed)
- {
- LogManager.Info("SystemManagementViewModel已释放,停止性能监控更新");
- _performanceTimer?.Stop();
- return;
- }
+ // 使用IdleEventManager注册性能监控任务,替代DispatcherTimer
+ const string taskId = "SystemManagement_PerformanceMonitor";
+
+ IdleEventManager.Instance.RegisterTask(
+ taskId,
+ UpdatePerformanceMetrics, // 要执行的操作
+ 30000, // 30秒间隔 (毫秒)
+ 5 // 中等优先级
+ );
+
+ LogManager.Info("SystemManagementViewModel性能监控已启动 (Idle事件模式)");
+ }
- // 更新内存使用
- var process = System.Diagnostics.Process.GetCurrentProcess();
- var memoryMB = process.WorkingSet64 / (1024 * 1024);
- MemoryUsage = $"{memoryMB} MB";
-
- // 更新运行时间
- var runTime = DateTime.Now - startTime;
- RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
-
- // 性能信息更新已合并到统一状态栏
- }
- catch (Exception ex)
+ ///
+ /// 更新性能指标 (Idle事件回调方法)
+ ///
+ private void UpdatePerformanceMetrics()
+ {
+ try
+ {
+ // 检查释放状态,避免在释放后继续更新UI
+ if (_disposed)
{
- LogManager.Error($"性能监控更新失败: {ex.Message}");
-
- // 🔧 修复:发生异常时也停止定时器
- if (!_disposed)
- {
- _performanceTimer?.Stop();
- }
+ LogManager.Info("SystemManagementViewModel已释放,停止性能监控更新");
+ IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
+ return;
}
- };
- _performanceTimer.Start();
-
- LogManager.Info("SystemManagementViewModel性能监控已启动");
+
+ // 更新内存使用
+ var process = System.Diagnostics.Process.GetCurrentProcess();
+ var memoryMB = process.WorkingSet64 / (1024 * 1024);
+ MemoryUsage = $"{memoryMB} MB";
+
+ // 更新运行时间
+ var runTime = DateTime.Now - _startTime;
+ RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
+
+ // 记录上次更新时间
+ _lastPerformanceUpdate = DateTime.Now;
+
+ LogManager.Debug($"性能指标已更新: 内存={MemoryUsage}, 运行时间={RunningTime}");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"性能监控更新失败: {ex.Message}");
+
+ // 发生异常时停止监控,避免持续错误
+ if (!_disposed)
+ {
+ IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
+ }
+ }
}
#endregion
@@ -671,7 +686,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
///
- /// 检查更新
+ /// 检查更新 (已优化为Idle事件监听)
///
private void ExecuteCheckUpdate()
{
@@ -679,16 +694,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
UpdateMainStatus("正在检查更新...");
- // 模拟检查更新
- System.Threading.Tasks.Task.Run(() =>
- {
- System.Threading.Thread.Sleep(2000);
-
- System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
+ // 使用Idle事件监听替代Thread.Sleep(2000)
+ const string taskId = "SystemManagement_CheckUpdate";
+ var startTime = DateTime.Now;
+
+ IdleEventManager.Instance.RegisterOnceTask(
+ taskId,
+ () => (DateTime.Now - startTime).TotalMilliseconds >= 2000, // 2秒后条件满足
+ () =>
{
try
{
- // 🔧 修复:检查释放状态,避免在释放后更新UI
+ // 检查释放状态,避免在释放后更新UI
if (_disposed)
{
LogManager.Info("SystemManagementViewModel已释放,跳过更新检查UI更新");
@@ -701,15 +718,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Error($"更新检查UI更新失败: {ex.Message}");
}
- }), System.Windows.Threading.DispatcherPriority.Background);
- });
+ },
+ 8 // 高优先级
+ );
- LogManager.Info("检查更新");
+ LogManager.Info("检查更新 (使用Idle事件监听)");
}, "检查更新");
}
///
- /// 生成性能报告
+ /// 生成性能报告 (已优化为Idle事件监听)
///
private void ExecuteGeneratePerformanceReport()
{
@@ -717,16 +735,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
UpdateMainStatus("正在生成性能报告...");
- // 模拟生成报告
- System.Threading.Tasks.Task.Run(() =>
- {
- System.Threading.Thread.Sleep(1500);
-
- System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
+ // 使用Idle事件监听替代Thread.Sleep(1500)
+ const string taskId = "SystemManagement_GenerateReport";
+ var startTime = DateTime.Now;
+
+ IdleEventManager.Instance.RegisterOnceTask(
+ taskId,
+ () => (DateTime.Now - startTime).TotalMilliseconds >= 1500, // 1.5秒后条件满足
+ () =>
{
try
{
- // 🔧 修复:检查释放状态,避免在释放后更新UI
+ // 检查释放状态,避免在释放后更新UI
if (_disposed)
{
LogManager.Info("SystemManagementViewModel已释放,跳过性能报告UI更新");
@@ -740,10 +760,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Error($"性能报告UI更新失败: {ex.Message}");
}
- }), System.Windows.Threading.DispatcherPriority.Background);
- });
+ },
+ 8 // 高优先级
+ );
- LogManager.Info("生成性能报告");
+ LogManager.Info("生成性能报告 (使用Idle事件监听)");
}, "生成性能报告");
}
@@ -949,13 +970,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Info("开始清理SystemManagementViewModel资源");
- // 🔧 修复:停止性能监控定时器
- if (_performanceTimer != null)
+ // 停止性能监控Idle任务,替代DispatcherTimer清理
+ try
{
- _performanceTimer.Stop();
- _performanceTimer.Tick -= null; // 取消事件订阅
- _performanceTimer = null;
- LogManager.Info("SystemManagementViewModel性能监控定时器已停止");
+ IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
+ LogManager.Info("SystemManagementViewModel性能监控Idle任务已停止");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Warning($"停止性能监控Idle任务时出现警告: {ex.Message}");
+ }
+
+ // 清理可能的一次性任务
+ try
+ {
+ IdleEventManager.Instance.UnregisterTask("SystemManagement_CheckUpdate");
+ IdleEventManager.Instance.UnregisterTask("SystemManagement_GenerateReport");
+ LogManager.Debug("SystemManagementViewModel一次性Idle任务已清理");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Debug($"清理一次性Idle任务时出现提示: {ex.Message}");
}
LogManager.Info("SystemManagementViewModel资源清理完成");