增加了同步UI刷新机制和定时器保底UI刷新机制
This commit is contained in:
parent
5d2ed56936
commit
1add8c6410
Binary file not shown.
@ -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
|
||||
{
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user