Explorar o código

fix(camera): GetSourceBuffer加锁+空保护, Dispose释放移入锁内, 修复段错误

根因:GetSourceBuffer不加Locker锁访问原生_pDest,与GrabRgb原生写及Dispose释放
竞争,关窗口时后台线程读已释放内存→段错误(0x80131506)。
- GetSourceBuffer: lock(Locker)+_pDest==Zero返回null(调用方Grab已按失败重试)
- Dispose: 释放_pDest/_capInfo.Buffer移入lock(Locker),与读访问互斥

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie hai 1 semana
pai
achega
f92a71d579
Modificáronse 1 ficheiros con 16 adicións e 6 borrados
  1. 16 6
      Camera/Camera.cs

+ 16 - 6
Camera/Camera.cs

@@ -131,12 +131,18 @@ namespace AutoFocusTool.Camera
             }
         }
 
-        /// <summary>取当前帧像素(24bpp BGR,width*height*3 字节,未翻转)。</summary>
+        /// <summary>取当前帧像素(24bpp BGR,width*height*3 字节,未翻转)。
+        /// 加 Locker 锁与 _pDest 空保护:避免与 GrabRgb 原生写、Dispose 释放竞争导致段错误。
+        /// _pDest 已释放(IntPtr.Zero)时返回 null,调用方按抓帧失败处理(重试)。</summary>
         public byte[] GetSourceBuffer()
         {
-            byte[] buf = new byte[_width * _height * 3];
-            Marshal.Copy(_pDest, buf, 0, buf.Length);
-            return buf;
+            lock (Locker)
+            {
+                if (_pDest == IntPtr.Zero) return null;
+                byte[] buf = new byte[_width * _height * 3];
+                Marshal.Copy(_pDest, buf, 0, buf.Length);
+                return buf;
+            }
         }
 
         /// <summary>卸载相机。</summary>
@@ -156,8 +162,12 @@ namespace AutoFocusTool.Camera
         public void Dispose()
         {
             try { UnInit(); } catch { }
-            if (_pDest != IntPtr.Zero) { Marshal.FreeCoTaskMem(_pDest); _pDest = IntPtr.Zero; }
-            if (_capInfo.Buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(_capInfo.Buffer); _capInfo.Buffer = IntPtr.Zero; }
+            // 在锁内释放:与 GetSourceBuffer/GrabRgb 的原生内存访问互斥,避免释放后被另一线程读到野指针。
+            lock (Locker)
+            {
+                if (_pDest != IntPtr.Zero) { Marshal.FreeCoTaskMem(_pDest); _pDest = IntPtr.Zero; }
+                if (_capInfo.Buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(_capInfo.Buffer); _capInfo.Buffer = IntPtr.Zero; }
+            }
         }
     }
 }