|
@@ -997,7 +997,7 @@ namespace TeamAAS_VP.Core
|
|
|
if (robot.TcpService.Count < 1)
|
|
if (robot.TcpService.Count < 1)
|
|
|
{
|
|
{
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.RobotName}{Lang.未连接}";
|
|
sta.Message = $"{r.RobotName}{Lang.未连接}";
|
|
@@ -1010,7 +1010,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{r.RobotName}{Lang.断开连接}!", MessageLevel.Error);
|
|
SendTaskMessage($"{r.RobotName}{Lang.断开连接}!", MessageLevel.Error);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.RobotName}{Lang.断开连接}";
|
|
sta.Message = $"{r.RobotName}{Lang.断开连接}";
|
|
@@ -1042,7 +1042,7 @@ namespace TeamAAS_VP.Core
|
|
|
if (scanner.TcpService.Count < 1)
|
|
if (scanner.TcpService.Count < 1)
|
|
|
{
|
|
{
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.ScannerName}{Lang.未连接}";
|
|
sta.Message = $"{r.ScannerName}{Lang.未连接}";
|
|
@@ -1055,7 +1055,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{r.ScannerName}{Lang.断开连接}!", MessageLevel.Error);
|
|
SendTaskMessage($"{r.ScannerName}{Lang.断开连接}!", MessageLevel.Error);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.ScannerName}{Lang.断开连接}";
|
|
sta.Message = $"{r.ScannerName}{Lang.断开连接}";
|
|
@@ -1084,7 +1084,7 @@ namespace TeamAAS_VP.Core
|
|
|
if (robot.TcpService.Count > 0)
|
|
if (robot.TcpService.Count > 0)
|
|
|
{
|
|
{
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.RobotName}{Lang.已连接}";
|
|
sta.Message = $"{r.RobotName}{Lang.已连接}";
|
|
@@ -1097,7 +1097,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{r.RobotName}{Lang.已连接}!", MessageLevel.Debug);
|
|
SendTaskMessage($"{r.RobotName}{Lang.已连接}!", MessageLevel.Debug);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == robotid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.RobotName}{Lang.已连接}";
|
|
sta.Message = $"{r.RobotName}{Lang.已连接}";
|
|
@@ -1125,7 +1125,7 @@ namespace TeamAAS_VP.Core
|
|
|
if (scanner.TcpService.Count > 0)
|
|
if (scanner.TcpService.Count > 0)
|
|
|
{
|
|
{
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.ScannerName}{Lang.已连接}";
|
|
sta.Message = $"{r.ScannerName}{Lang.已连接}";
|
|
@@ -1138,7 +1138,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{r.ScannerName}{Lang.已连接}!", MessageLevel.Debug);
|
|
SendTaskMessage($"{r.ScannerName}{Lang.已连接}!", MessageLevel.Debug);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
var sta = Status.FirstOrDefault(s => s.ID == scannerid);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{r.ScannerName}{Lang.已连接}";
|
|
sta.Message = $"{r.ScannerName}{Lang.已连接}";
|
|
@@ -1159,7 +1159,7 @@ namespace TeamAAS_VP.Core
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == feeder.Id);
|
|
var sta = Status.FirstOrDefault(s => s.ID == feeder.Id);
|
|
|
if (state)
|
|
if (state)
|
|
|
{
|
|
{
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{feeder.Name}{Lang.已连接}";
|
|
sta.Message = $"{feeder.Name}{Lang.已连接}";
|
|
@@ -1170,7 +1170,7 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{feeder.Name}{Lang.未连接}";
|
|
sta.Message = $"{feeder.Name}{Lang.未连接}";
|
|
@@ -1194,7 +1194,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
if (state)
|
|
if (state)
|
|
|
{
|
|
{
|
|
|
- App.Current.Dispatcher.Invoke(new Action(() =>
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{camera.CameraName}{Lang.已连接}";
|
|
sta.Message = $"{camera.CameraName}{Lang.已连接}";
|
|
|
sta.Background = new SolidColorBrush(Colors.Green);
|
|
sta.Background = new SolidColorBrush(Colors.Green);
|
|
@@ -1203,7 +1203,7 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- App.Current.Dispatcher.Invoke(new Action(() =>
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{camera.CameraName}{Lang.断开连接}";
|
|
sta.Message = $"{camera.CameraName}{Lang.断开连接}";
|
|
|
sta.Background = new SolidColorBrush(Colors.Red);
|
|
sta.Background = new SolidColorBrush(Colors.Red);
|
|
@@ -1225,7 +1225,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{plc.Name}{Lang.已连接}!", MessageLevel.Debug);
|
|
SendTaskMessage($"{plc.Name}{Lang.已连接}!", MessageLevel.Debug);
|
|
|
if (sta == null) return;
|
|
if (sta == null) return;
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{plc.Name}{Lang.已连接}";
|
|
sta.Message = $"{plc.Name}{Lang.已连接}";
|
|
@@ -1236,7 +1236,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"{plc.Name}{Lang.断开连接}!", MessageLevel.Error);
|
|
SendTaskMessage($"{plc.Name}{Lang.断开连接}!", MessageLevel.Error);
|
|
|
if (sta == null) return;
|
|
if (sta == null) return;
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"{plc.Name}{Lang.未连接}";
|
|
sta.Message = $"{plc.Name}{Lang.未连接}";
|
|
@@ -1259,7 +1259,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"电批{Lang.已连接}!", MessageLevel.Debug);
|
|
SendTaskMessage($"电批{Lang.已连接}!", MessageLevel.Debug);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
|
|
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"电批{Lang.已连接}";
|
|
sta.Message = $"电批{Lang.已连接}";
|
|
@@ -1270,7 +1270,7 @@ namespace TeamAAS_VP.Core
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"电批{Lang.未连接}!", MessageLevel.Error);
|
|
SendTaskMessage($"电批{Lang.未连接}!", MessageLevel.Error);
|
|
|
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
|
|
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
|
|
|
- App.Current.Dispatcher.Invoke(new
|
|
|
|
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new
|
|
|
Action(() =>
|
|
Action(() =>
|
|
|
{
|
|
{
|
|
|
sta.Message = $"电批{Lang.未连接}";
|
|
sta.Message = $"电批{Lang.未连接}";
|
|
@@ -2634,7 +2634,11 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// 等待所有并发 ToolBlock 执行完成
|
|
// 等待所有并发 ToolBlock 执行完成
|
|
|
|
|
+ var concurrentWatch = Stopwatch.StartNew();
|
|
|
|
|
+ LogHelper.WriteLogInfo($"[PLC-TRACE] {fixedCameraTraceId} concurrent ToolBlock execution starting, taskCount={procedureTasks.Count}, thread={Thread.CurrentThread.ManagedThreadId}, time={DateTime.Now:HH:mm:ss.fff}");
|
|
|
await Task.WhenAll(procedureTasks);
|
|
await Task.WhenAll(procedureTasks);
|
|
|
|
|
+ concurrentWatch.Stop();
|
|
|
|
|
+ LogHelper.WriteLogInfo($"[PLC-TRACE] {fixedCameraTraceId} concurrent ToolBlock execution done, taskCount={procedureTasks.Count}, elapsedMs={concurrentWatch.ElapsedMilliseconds}, thread={Thread.CurrentThread.ManagedThreadId}, time={DateTime.Now:HH:mm:ss.fff}");
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2646,6 +2650,7 @@ namespace TeamAAS_VP.Core
|
|
|
//等待所有的图像处理流程处理完成
|
|
//等待所有的图像处理流程处理完成
|
|
|
//之前版本使用的是lock机制无法进行并发操作,目前能完美进行并发且能等待所有任务完成
|
|
//之前版本使用的是lock机制无法进行并发操作,目前能完美进行并发且能等待所有任务完成
|
|
|
// 异步等待 countdown,避免同步阻塞线程池线程
|
|
// 异步等待 countdown,避免同步阻塞线程池线程
|
|
|
|
|
+ LogHelper.WriteLogInfo($"[PLC-TRACE] {fixedCameraTraceId} countdown wait start, expected={countdown.InitialCount}, current={countdown.CurrentCount}, thread={Thread.CurrentThread.ManagedThreadId}, time={DateTime.Now:HH:mm:ss.fff}");
|
|
|
bool countdownCompleted;
|
|
bool countdownCompleted;
|
|
|
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
|
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
|
|
{
|
|
{
|
|
@@ -2659,6 +2664,7 @@ namespace TeamAAS_VP.Core
|
|
|
countdownCompleted = false;
|
|
countdownCompleted = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ LogHelper.WriteLogInfo($"[PLC-TRACE] {fixedCameraTraceId} countdown wait done, completed={countdownCompleted}, remaining={countdown.CurrentCount}, thread={Thread.CurrentThread.ManagedThreadId}, time={DateTime.Now:HH:mm:ss.fff}");
|
|
|
if (!countdownCompleted)
|
|
if (!countdownCompleted)
|
|
|
{
|
|
{
|
|
|
SendTaskMessage($"检测流程超时!预期{countdown.InitialCount}个模板完成,实际仅完成{countdown.InitialCount - countdown.CurrentCount}个,按NG处理", MessageLevel.Alarm);
|
|
SendTaskMessage($"检测流程超时!预期{countdown.InitialCount}个模板完成,实际仅完成{countdown.InitialCount - countdown.CurrentCount}个,按NG处理", MessageLevel.Alarm);
|
|
@@ -3764,10 +3770,12 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
- App.Current.Dispatcher.Invoke(() =>
|
|
|
|
|
|
|
+ // 使用 BeginInvoke(Background) 异步通知 UI
|
|
|
|
|
+ // Background 优先级确保用户输入(Normal)优先处理
|
|
|
|
|
+ _ = App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
{
|
|
{
|
|
|
_eventAggregator.GetEvent<LockFinishNotification>().Publish(lockResult1);
|
|
_eventAggregator.GetEvent<LockFinishNotification>().Publish(lockResult1);
|
|
|
- });
|
|
|
|
|
|
|
+ }), System.Windows.Threading.DispatcherPriority.Background);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//排序
|
|
//排序
|
|
@@ -4300,18 +4308,31 @@ namespace TeamAAS_VP.Core
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
- /// 定时将消息队列批量推送到 UI 线程,200ms 一次,单次 BeginInvoke
|
|
|
|
|
|
|
+ /// 定时将消息队列批量推送到 UI 线程,200ms 一次
|
|
|
|
|
+ /// 使用 DispatcherPriority.Background + 分批出让,避免 WPF 布局洪水饿死用户输入
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
private void FlushMessageQueue()
|
|
private void FlushMessageQueue()
|
|
|
{
|
|
{
|
|
|
if (_messageQueue.IsEmpty) return;
|
|
if (_messageQueue.IsEmpty) return;
|
|
|
- App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
|
|
|
|
|
+ // 先全部取出到本地列表,快速释放队列
|
|
|
|
|
+ var batch = new List<MessageStruct>();
|
|
|
|
|
+ while (_messageQueue.TryDequeue(out var item))
|
|
|
|
|
+ batch.Add(item);
|
|
|
|
|
+ if (batch.Count == 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ // InvokeAsync 配合 async Task 避免 async void 陷阱;
|
|
|
|
|
+ // Background 优先级确保用户输入(Input 优先级)优先处理
|
|
|
|
|
+ App.Current.Dispatcher.InvokeAsync(async () =>
|
|
|
{
|
|
{
|
|
|
- while (_messageQueue.TryDequeue(out var item))
|
|
|
|
|
|
|
+ for (int i = 0; i < batch.Count; i++)
|
|
|
{
|
|
{
|
|
|
- _eventAggregator.GetEvent<TaskMessageNotification>().Publish(item);
|
|
|
|
|
|
|
+ _eventAggregator.GetEvent<TaskMessageNotification>().Publish(batch[i]);
|
|
|
|
|
+ // 每 5 条出让 UI 线程,让 WPF 布局和用户输入有机会执行
|
|
|
|
|
+ if (i % 5 == 4 && i < batch.Count - 1)
|
|
|
|
|
+ await System.Windows.Threading.Dispatcher.Yield(System.Windows.Threading.DispatcherPriority.Input);
|
|
|
}
|
|
}
|
|
|
- }));
|
|
|
|
|
|
|
+ if (batch.Count > 50)
|
|
|
|
|
+ }), System.Windows.Threading.DispatcherPriority.Background);
|
|
|
}
|
|
}
|
|
|
public bool concurrenty = true;
|
|
public bool concurrenty = true;
|
|
|
public void CurrentRunStatus()
|
|
public void CurrentRunStatus()
|