增加了同步UI刷新机制和定时器保底UI刷新机制

This commit is contained in:
tian 2025-08-19 23:35:36 +08:00
parent 5d2ed56936
commit 1add8c6410
3 changed files with 325 additions and 14 deletions

View File

@ -411,18 +411,18 @@ namespace NavisworksTransport
LogManager.Warning("*** RouteGenerated事件没有订阅者 ***");
}
// RouteGenerated事件使用立即执行确保UI及时更新
// 测试强制同步处理使用高优先级QueueUIUpdate代替立即执行
if (_uiStateManager != null)
{
LogManager.Info("*** 使用UIStateManager立即执行RouteGenerated事件 ***");
_uiStateManager.ExecuteImmediateUIUpdate(() =>
LogManager.Info("*** 使用高优先级强制同步处理RouteGenerated事件 ***");
_uiStateManager.QueueUIUpdateWithForcedSync(() =>
{
LogManager.Info($"*** 立即执行RouteGenerated事件: {route?.Name} ***");
LogManager.Info($"*** 强制同步队列中执行RouteGenerated事件: {route?.Name} ***");
RouteGenerated?.Invoke(this, eventArgs);
// 向后兼容的事件
RouteGenerated_Legacy?.Invoke(this, route);
LogManager.Info($"*** RouteGenerated事件立即执行完成: {route?.Name} ***");
}, $"RouteGenerated事件({route?.Name})");
LogManager.Info($"*** RouteGenerated事件强制同步执行完成: {route?.Name} ***");
}, UIUpdatePriority.Critical, $"RouteGenerated强制同步事件({route?.Name})");
}
else
{

View File

@ -23,6 +23,8 @@ 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 volatile bool _isProcessing = false;
private volatile bool _isDisposed = false;
@ -312,6 +314,150 @@ namespace NavisworksTransport.Core
await ExecuteBatchUIUpdate(updates, 10000);
}
/// <summary>
/// 同步版本的批量UI更新操作用于强制同步处理
/// 不使用异步机制直接在当前线程中处理UI操作
/// </summary>
/// <param name="updates">要执行的UI更新操作数组</param>
/// <param name="timeout">超时时间毫秒默认5000ms</param>
public void ExecuteBatchUIUpdateSync(Action[] updates, int timeout = 5000)
{
if (updates == null || updates.Length == 0)
{
return;
}
LogManager.Info($"开始同步执行{updates.Length}个UI更新操作");
var exceptions = new List<Exception>();
// 如果已经在UI线程中直接执行
if (IsUIThread)
{
LogManager.Info("当前已在UI线程直接同步执行批量操作");
foreach (var update in updates)
{
try
{
update?.Invoke();
}
catch (Exception ex)
{
exceptions.Add(ex);
LogManager.Error($"同步批量UI更新中的操作失败: {ex.Message}");
}
}
}
else
{
// 使用同步方式切换到UI线程
var completed = false;
Exception syncException = null;
var resetEvent = new ManualResetEventSlim(false);
LogManager.Info("切换到UI线程同步执行批量操作");
if (_uiContext != null)
{
_uiContext.Send(_ =>
{
try
{
LogManager.Info($"SynchronizationContext中同步执行{updates.Length}个操作");
foreach (var update in updates)
{
try
{
update?.Invoke();
}
catch (Exception ex)
{
exceptions.Add(ex);
LogManager.Error($"同步批量UI更新中的操作失败: {ex.Message}");
}
}
completed = true;
}
catch (Exception ex)
{
syncException = ex;
}
finally
{
resetEvent.Set();
}
}, null);
}
else
{
// 回退到Control.Invoke
var mainForm = GetMainForm();
if (mainForm != null)
{
mainForm.Invoke(new Action(() =>
{
try
{
LogManager.Info($"Control.Invoke中同步执行{updates.Length}个操作");
foreach (var update in updates)
{
try
{
update?.Invoke();
}
catch (Exception ex)
{
exceptions.Add(ex);
LogManager.Error($"同步批量UI更新中的操作失败: {ex.Message}");
}
}
completed = true;
}
catch (Exception ex)
{
syncException = ex;
}
finally
{
resetEvent.Set();
}
}));
}
else
{
throw new InvalidOperationException("无法找到UI上下文来执行同步批量UI更新");
}
}
// 等待完成或超时
if (!resetEvent.Wait(timeout))
{
LogManager.Error($"同步批量UI更新执行超时{timeout}ms");
throw new TimeoutException($"同步批量UI更新执行超时{timeout}ms");
}
// 检查执行结果
if (syncException != null)
{
throw new Exception("同步批量UI更新执行失败", syncException);
}
if (!completed)
{
throw new InvalidOperationException("同步批量UI更新未正确完成");
}
}
// 如果有任何异常,抛出聚合异常
if (exceptions.Count > 0)
{
LogManager.Error($"同步批量UI更新过程中发生{exceptions.Count}个错误");
throw new AggregateException("同步批量UI更新过程中发生错误", exceptions);
}
LogManager.Info($"同步批量UI更新成功完成{updates.Length}个操作");
}
#endregion
#region
@ -321,7 +467,7 @@ namespace NavisworksTransport.Core
/// </summary>
/// <param name="operation">UI更新操作</param>
/// <param name="priority">操作优先级</param>
public void QueueUIUpdate(Action operation, UIUpdatePriority priority = UIUpdatePriority.Normal)
public void QueueUIUpdate(Action operation, UIUpdatePriority priority = UIUpdatePriority.Normal, bool forceSync = false)
{
if (_isDisposed || operation == null)
{
@ -338,10 +484,78 @@ namespace NavisworksTransport.Core
_updateQueue.Enqueue(updateOperation);
// 如果当前没有在处理,启动处理
// 如果当前没有在处理,根据参数选择处理方式
if (!_isProcessing)
{
_ = Task.Run(ProcessQueuedUpdates);
if (forceSync || priority == UIUpdatePriority.Critical)
{
// 强制同步处理直接处理队列不依赖Task.Run
LogManager.Info($"强制同步处理UI队列优先级: {priority}, 队列长度: {_updateQueue.Count}");
try
{
ProcessQueuedUpdates(forcedSync: true).GetAwaiter().GetResult();
}
catch (Exception ex)
{
LogManager.Error($"强制同步处理队列失败: {ex.Message}");
// 回退到异步处理
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
EnsureFlushTimerRunning();
}
}
else
{
// 普通异步处理 + 保底定时器
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
EnsureFlushTimerRunning();
}
}
}
/// <summary>
/// 强制同步处理UI更新操作便捷方法
/// 操作会先入队,然后立即同步处理整个队列
/// </summary>
/// <param name="operation">UI更新操作</param>
/// <param name="priority">操作优先级</param>
/// <param name="operationType">操作类型描述,用于日志记录</param>
public void QueueUIUpdateWithForcedSync(Action operation, UIUpdatePriority priority = UIUpdatePriority.High, string operationType = "强制同步UI更新")
{
LogManager.Info($"*** 开始{operationType},优先级: {priority} ***");
QueueUIUpdate(operation, priority, forceSync: true);
LogManager.Info($"*** {operationType}完成 ***");
}
/// <summary>
/// 强制刷新当前队列中的所有操作(不添加新操作)
/// 直接同步处理现有队列代替Task.Run
/// </summary>
/// <param name="operationType">操作类型描述,用于日志记录</param>
public void ForceFlushQueue(string operationType = "强制刷新队列")
{
if (_updateQueue.IsEmpty)
{
LogManager.Info($"{operationType}: 队列为空,无需处理");
return;
}
if (_isProcessing)
{
LogManager.Info($"{operationType}: 已在处理中,跳过");
return;
}
LogManager.Info($"*** 开始{operationType},当前队列长度: {_updateQueue.Count} ***");
try
{
ProcessQueuedUpdates(forcedSync: true).GetAwaiter().GetResult();
LogManager.Info($"*** {operationType}成功完成 ***");
}
catch (Exception ex)
{
LogManager.Error($"*** {operationType}失败: {ex.Message} ***");
throw;
}
}
@ -460,10 +674,86 @@ namespace NavisworksTransport.Core
}
}
/// <summary>
/// 确保刷新定时器正在运行
/// 作为队列处理的保底机制防止Task.Run失败导致的队列积压
/// </summary>
private void EnsureFlushTimerRunning()
{
try
{
// 如果已经有定时器在运行,或者队列为空,则不需要启动
if (_flushTimer != null || _updateQueue.IsEmpty)
{
return;
}
LogManager.Info($"启动保底定时器,检查间隔: {_flushInterval}ms");
_flushTimer = new System.Threading.Timer(OnFlushTimerTick, null, _flushInterval, _flushInterval);
}
catch (Exception ex)
{
LogManager.Error($"启动保底定时器失败: {ex.Message}");
}
}
/// <summary>
/// 保底定时器回调 - 定期检查并处理积压的队列
/// </summary>
private void OnFlushTimerTick(object state)
{
try
{
// 如果没有积压的操作,停止定时器
if (_updateQueue.IsEmpty)
{
StopFlushTimer();
return;
}
// 如果当前正在处理,等待下次检查
if (_isProcessing)
{
return;
}
LogManager.Info($"保底定时器检测到队列积压({_updateQueue.Count}个操作),强制处理");
// 强制启动队列处理(保底定时器使用异步处理)
_ = Task.Run(() => ProcessQueuedUpdates(forcedSync: false));
}
catch (Exception ex)
{
LogManager.Error($"保底定时器处理失败: {ex.Message}");
}
}
/// <summary>
/// 停止保底定时器
/// </summary>
private void StopFlushTimer()
{
try
{
if (_flushTimer != null)
{
LogManager.Info("停止保底定时器");
_flushTimer.Dispose();
_flushTimer = null;
}
}
catch (Exception ex)
{
LogManager.Error($"停止保底定时器失败: {ex.Message}");
}
}
/// <summary>
/// 处理队列中的UI更新操作
/// </summary>
private async Task ProcessQueuedUpdates()
/// <param name="forcedSync">是否强制同步处理(不使用异步)</param>
private async Task ProcessQueuedUpdates(bool forcedSync = false)
{
lock (_operationLock)
{
@ -492,13 +782,31 @@ namespace NavisworksTransport.Core
// 按优先级排序
operations = operations.OrderByDescending(op => op.Priority).ToList();
LogManager.Info($"开始处理{operations.Count}个排队的UI更新操作");
LogManager.Info($"开始处理{operations.Count}个排队的UI更新操作,强制同步: {forcedSync}");
// 批量执行操作
var actions = operations.Select(op => op.Operation).ToArray();
await ExecuteBatchUIUpdate(actions);
LogManager.Info($"完成处理{operations.Count}个UI更新操作");
if (forcedSync)
{
// 使用同步版本的批量更新
LogManager.Info("使用同步方式处理UI更新队列");
ExecuteBatchUIUpdateSync(actions);
LogManager.Info($"同步处理{operations.Count}个UI更新操作完成");
}
else
{
// 使用异步版本的批量更新
LogManager.Info("使用异步方式处理UI更新队列");
await ExecuteBatchUIUpdate(actions);
LogManager.Info($"异步处理{operations.Count}个UI更新操作完成");
}
// 处理完成后,如果队列为空,停止保底定时器
if (_updateQueue.IsEmpty)
{
StopFlushTimer();
}
}
catch (Exception ex)
{
@ -580,6 +888,9 @@ namespace NavisworksTransport.Core
_isDisposed = true;
// 停止并清理保底定时器
StopFlushTimer();
// 清空队列
ClearUpdateQueue();