Explorar o código

fix(d2-02): 根治预览残帧竞态 I-1——FrameReceived/Stopped lambda 用局部 client 比对字段 _mjpeg,旧实例残帧与 Stopped 被挡(关画面不回写、不串台)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie hai 1 día
pai
achega
8585acf50d

+ 10 - 4
ivf_tl_operate_2.0/ivf_tl_Operate/View/HouseDebugPageView.xaml.cs

@@ -215,14 +215,20 @@ namespace ivf_tl_Operate.View
                 if (string.IsNullOrEmpty(sessionId)) { AddMessageInfo("未借用会话,无法预览(请先初始化)"); return; }
 
                 // 每次开预览 new 新实例(MjpegStreamClient 一次性,不可复用)
-                _mjpeg = new MjpegStreamClient(ivf_tl_Operate.Helpers.ControlClient.BaseUrl);
-                _mjpeg.FrameReceived += img => Dispatcher.Invoke(() => { _previewImage.Source = img; });
-                _mjpeg.Stopped += reason => Dispatcher.Invoke(() =>
+                var client = new MjpegStreamClient(ivf_tl_Operate.Helpers.ControlClient.BaseUrl);
+                _mjpeg = client;
+                client.FrameReceived += img => Dispatcher.Invoke(() =>
                 {
+                    if (_mjpeg != client) return;        // 已被 CloseVideo 换/清,丢弃残帧(避免关画面后残帧写回)
+                    _previewImage.Source = img;
+                });
+                client.Stopped += reason => Dispatcher.Invoke(() =>
+                {
+                    if (_mjpeg != client) return;        // 旧实例的 Stopped 不串台到新会话
                     isOpen = false;
                     AddMessageInfo($"⚠ {reason}");   // 明确提示操作人员手动重开(不自动重连)
                 });
-                _mjpeg.Start(sessionId);
+                client.Start(sessionId);
                 isOpen = true;
                 AddMessageInfo("图像已打开(MJPEG 实时预览)");
             }