多线程图像处理管道中SynchronizationLockException异常原因排查
线程化图像处理管道中的SynchronizationLockException异常排查
我正在开发一个每个处理步骤对应一个线程的图像处理管道,但一直受SynchronizationLockException异常困扰,无法找出异常触发的原因。
相关核心代码
int bufferWriterPointer; lock (_bufferPointerLock) { bufferWriterPointer = _bufferWriterPointer++; if (_bufferWriterPointer == BufferNbr) _bufferWriterPointer = 0; } BitmapFrame frame = BytesBuffers[bufferWriterPointer]; lock(frame) { SIMDHelper.Copy(newBuffer, frame.Data); } lock (_bufferPointerLock) UnReadBufferNbr++;
BitmapFrame类定义
public class BitmapFrame : Frame { public Bitmap Bitmap { get; set; } public BitmapFrame(byte[] data) : base(data) { Bitmap = null; } public BitmapFrame(byte[] data, Bitmap bmp) : base(data) { Bitmap = bmp; } }
SIMDHelper类实现
public static void Copy(byte[] sourceBuffer, byte[] destinationBuffer) { GCHandle pinnedSrcBuffer = GCHandle.Alloc(sourceBuffer, GCHandleType.Pinned); IntPtr srcBufferPtr = pinnedSrcBuffer.AddrOfPinnedObject(); GCHandle pinnedDestBuffer = GCHandle.Alloc(destinationBuffer, GCHandleType.Pinned); IntPtr destBuffer = pinnedDestBuffer.AddrOfPinnedObject(); SIMD.SimdCopy(srcBufferPtr, sourceBuffer.Length, sourceBuffer.Length, 1, 1, destBuffer, sourceBuffer.Length); pinnedDestBuffer.Free(); pinnedSrcBuffer.Free(); }
DllImport声明
[DllImport(SIMD_LIBRARY_FILENAME, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void SimdCopy(IntPtr sourcePointer, nint sourceStride, nint width, nint height, nint pixelSize, IntPtr destinationPointer, nint destinationStride);
异常触发的可能原因及排查方向
- 锁定不可锁定对象:
SynchronizationLockException通常因尝试锁定值类型或未同步对象触发。检查frame是否可能为null,或Frame基类是否存在导致BitmapFrame无法作为锁对象的逻辑;同时确认BytesBuffers中的元素都是有效引用类型实例,未被意外替换。 - 对象生命周期冲突:若
BytesBuffers中的BitmapFrame实例被多线程提前回收、替换,会导致锁定时对象状态异常。排查是否有其他线程修改BytesBuffers内容,或BitmapFrame实例被不当释放。 - 锁所有权冲突:尽管当前代码无明显嵌套锁,但
SIMDHelper.Copy内部若涉及其他同步操作,或frame.Data访问触发额外锁逻辑,可能引发线程所有权冲突。可尝试将锁对象改为frame.Data(若为引用类型),或给每个BitmapFrame分配专属锁对象。 - GCHandle操作副作用:
SIMDHelper.Copy中的缓冲区固定操作虽直接引发异常概率低,但需检查frame.Data是否在拷贝过程中被其他线程修改或释放。
建议修复尝试
- 给每个
BitmapFrame添加专属锁对象:
public class BitmapFrame : Frame { public Bitmap Bitmap { get; set; } public readonly object LockObj = new object(); // 专属锁对象 public BitmapFrame(byte[] data) : base(data) { Bitmap = null; } public BitmapFrame(byte[] data, Bitmap bmp) : base(data) { Bitmap = bmp; } }
修改锁定逻辑:
lock(frame.LockObj) { SIMDHelper.Copy(newBuffer, frame.Data); }
强化
BytesBuffers线程安全性:确保仅有单个线程修改_bufferWriterPointer和BytesBuffers内容,或在访问数组时添加同步保护。添加空值检查:避免空引用引发连锁异常:
BitmapFrame frame = BytesBuffers[bufferWriterPointer]; if (frame != null) { lock(frame.LockObj) { SIMDHelper.Copy(newBuffer, frame.Data); } }
内容的提问来源于stack exchange,提问作者Hidden_Bad
相关产品推荐
相关产品推荐

