You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程图像处理管道中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是否在拷贝过程中被其他线程修改或释放。

建议修复尝试

  1. 给每个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);
}
  1. 强化BytesBuffers线程安全性:确保仅有单个线程修改_bufferWriterPointer和BytesBuffers内容,或在访问数组时添加同步保护。

  2. 添加空值检查:避免空引用引发连锁异常:

BitmapFrame frame = BytesBuffers[bufferWriterPointer];
if (frame != null)
{
    lock(frame.LockObj)
    {
        SIMDHelper.Copy(newBuffer, frame.Data);
    }
}

内容的提问来源于stack exchange,提问作者Hidden_Bad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:05:29