用Idle机制改造UI管理框架

This commit is contained in:
tian 2025-09-08 10:01:20 +08:00
parent 9924c3b304
commit 3732c6fa99
7 changed files with 662 additions and 121 deletions

View File

@ -114,6 +114,9 @@
<!-- Core - UI State Management -->
<Compile Include="src\Core\UIStateManager.cs" />
<!-- Core - Idle Event Management -->
<Compile Include="src\Core\IdleEventManager.cs" />
<!-- Commands - Command Pattern Framework (for testing) -->
<Compile Include="src\Commands\IPathPlanningCommand.cs" />

View File

@ -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动画系统改进文档
- doc/working/idle_event_animation_strategy.md动画系统改进文档

View File

@ -0,0 +1,442 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Utils;
namespace NavisworksTransport.Core
{
/// <summary>
/// Idle事件统一管理器
/// 提供基于Application.Idle事件的任务调度系统改善UI性能
/// </summary>
public class IdleEventManager : IDisposable
{
#region
private static IdleEventManager _instance;
private static readonly object _instanceLock = new object();
/// <summary>
/// 获取IdleEventManager的单例实例
/// </summary>
public static IdleEventManager Instance
{
get
{
if (_instance == null)
{
lock (_instanceLock)
{
if (_instance == null)
{
_instance = new IdleEventManager();
}
}
}
return _instance;
}
}
#endregion
#region
private readonly Dictionary<string, IdleTask> _tasks = new Dictionary<string, IdleTask>();
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
/// <summary>
/// 注册持续任务
/// </summary>
/// <param name="taskId">任务ID</param>
/// <param name="action">要执行的操作</param>
/// <param name="minIntervalMs">最小执行间隔(毫秒)</param>
/// <param name="priority">任务优先级(数字越大优先级越高)</param>
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}");
}
}
/// <summary>
/// 注册一次性任务(满足条件后执行一次)
/// </summary>
/// <param name="taskId">任务ID</param>
/// <param name="condition">执行条件</param>
/// <param name="action">要执行的操作</param>
/// <param name="priority">任务优先级</param>
public void RegisterOnceTask(string taskId, Func<bool> 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}");
}
}
/// <summary>
/// 取消注册任务
/// </summary>
/// <param name="taskId">任务ID</param>
public void UnregisterTask(string taskId)
{
lock (_tasksLock)
{
if (_tasks.Remove(taskId))
{
LogManager.Info($"取消注册Idle任务: {taskId}");
}
if (_tasks.Count == 0)
{
Unsubscribe();
}
}
}
/// <summary>
/// 暂停任务
/// </summary>
/// <param name="taskId">任务ID</param>
public void PauseTask(string taskId)
{
lock (_tasksLock)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.IsPaused = true;
LogManager.Debug($"暂停Idle任务: {taskId}");
}
}
}
/// <summary>
/// 恢复任务
/// </summary>
/// <param name="taskId">任务ID</param>
public void ResumeTask(string taskId)
{
lock (_tasksLock)
{
if (_tasks.TryGetValue(taskId, out var task))
{
task.IsPaused = false;
LogManager.Debug($"恢复Idle任务: {taskId}");
}
}
}
/// <summary>
/// 获取当前注册的任务数量
/// </summary>
public int TaskCount
{
get
{
lock (_tasksLock)
{
return _tasks.Count;
}
}
}
/// <summary>
/// 获取活跃任务数量(未暂停的任务)
/// </summary>
public int ActiveTaskCount
{
get
{
lock (_tasksLock)
{
return _tasks.Values.Count(t => !t.IsPaused);
}
}
}
#endregion
#region Idle事件处理
/// <summary>
/// 确保已订阅Idle事件
/// </summary>
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}");
}
}
}
/// <summary>
/// 取消订阅Idle事件
/// </summary>
private void Unsubscribe()
{
if (_isSubscribed)
{
try
{
Application.Idle -= OnApplicationIdle;
_isSubscribed = false;
LogManager.Debug("已取消订阅Application.Idle事件");
}
catch (Exception ex)
{
LogManager.Error($"取消订阅Application.Idle事件失败: {ex.Message}");
}
}
}
/// <summary>
/// Application.Idle事件处理器
/// </summary>
private void OnApplicationIdle(object sender, EventArgs e)
{
if (_isDisposed)
return;
var now = DateTime.Now;
List<IdleTask> tasksToExecute = new List<IdleTask>();
// 收集需要执行的任务
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<string>();
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
/// <summary>
/// 获取任务信息(用于调试)
/// </summary>
/// <returns>任务信息字符串</returns>
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
/// <summary>
/// Idle任务信息
/// </summary>
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<bool> Condition { get; set; }
}
#endregion
}
}

View File

@ -23,8 +23,7 @@ namespace NavisworksTransport.Core
private readonly SynchronizationContext _uiContext;
private readonly object _operationLock = new object();
private readonly ConcurrentQueue<UIUpdateOperation> _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
}
/// <summary>
/// 确保刷新定时器正在运行
/// 确保Idle处理器在运行处理可能积压的UI操作
/// 作为队列处理的保底机制防止Task.Run失败导致的队列积压
/// </summary>
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}");
}
}
/// <summary>
/// 保底定时器回调 - 定期检查并处理积压的队列
/// Idle事件处理器 - 检查并处理积压的队列
/// </summary>
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}");
}
}
/// <summary>
/// 停止保底定时
/// 停止Idle队列处理
/// </summary>
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();

View File

@ -1372,6 +1372,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 动画完成后更新碰撞检测状态
/// </summary>
/// <summary>
/// 动画完成后更新碰撞检测状态
/// </summary>
@ -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
}
}
/// <summary>
/// 检查碰撞检测是否完成
/// </summary>
private bool IsCollisionDetectionComplete()
{
try
{
// 检查ClashDetectiveIntegration是否完成了碰撞测试创建
if (_clashIntegration != null)
{
// 简单的完成检查假设动画结束后1秒内碰撞检测应该完成
// 这里可以添加更具体的完成检查逻辑
return true; // 临时返回true表示可以立即处理
}
return false;
}
catch (Exception ex)
{
LogManager.Error($"检查碰撞检测完成状态失败: {ex.Message}");
return true; // 出错时认为已完成,避免无限等待
}
}
/// <summary>
/// 生成碰撞检测报告数据
/// </summary>

View File

@ -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
}
/// <summary>
/// 启动性能监控
/// 启动性能监控 (已优化为Idle事件)
/// </summary>
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)
/// <summary>
/// 更新性能指标 (Idle事件回调方法)
/// </summary>
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
}
/// <summary>
/// 检查更新
/// 检查更新 (已优化为Idle事件监听)
/// </summary>
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事件监听)");
}, "检查更新");
}
/// <summary>
/// 生成性能报告
/// 生成性能报告 (已优化为Idle事件监听)
/// </summary>
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资源清理完成");