【问题标题】:Bitmap region is already locked, multi-threaded environment位图区域已经被锁定,多线程环境
【发布时间】:2009-10-12 03:53:27
【问题描述】:

我正在使用通过多个​​线程调用主函数的 API。我试图通过该函数访问另一个类中的位图并从中写入,但即使在将其设置为使用完全不同的对象实例后,我仍遇到 InvalidOperationException:位图区域已锁定。

我已经尝试在 main 函数和调用 Bitmap.LockBits(...) 的位置锁定代码。是的,我完成后正在调用 UnlockBits。

    /* Part of Class B */
    public Surface imageSurface //Surface is a field of pixels, more or less.
    {
        get
        {
            if (_CurrImage != null && _imageSurface == null)
            {

                _imageSurface = Surface.CopyFromBitmap(_CurrImage);
                return Surface.CopyFromBitmap(_imageSurface.CreateAliasedBitmap());
            }
            else
            {
                Surface clearPixel = new Surface(1, 1);
                clearPixel[0, 0] = ColorBgra.FromBgra(255, 255, 255, 0);
                return clearPixel;
            }
        }
    }
    /* the "main" function, Class A */
    public override void Render(ClassBPrototype parameters, ...)
    {
        ClassB token = (ClassB)parameters; // Here we go again~!
        ...
        Surface ourSurface = dstArgs.Surface;
        if (token.imageSurface.Size != null)
        {
            ourSurface = token.imageSurface;
        }

        lock(typeof(ClassA))
        {
            for (int lRectangleIndex = ...)
            {
                Rectangle lRectangle = rois[lRectangleIndex];

                for (int y = ...)
                {
                    surfaceY = (ourSurface.Height / 2) - (y - (int)CenterY);

                    for (int x = ...)
                    {
                        surfaceX = (ourSurface.Width / 2) - (x - (int)CenterX);
                        if (surfaceX >= 0 && surfaceX < ourSurface.Width && surfaceY >= 0 && surfaceY < ourSurface.Height)
                        {
                            dstArgs.Surface[x, y] = ourSurface[surfaceX, surfaceY];
                        }
                        else
                        {
                            dstArgs.Surface[x, y] = ColorBgra.FromBgra(255, 255, 255, 0);
                        }

                    }
                }
            }
        }
    }

【问题讨论】:

  • 请发布一个小而完整的示例来演示该问题。
  • @Andrew:我的想法完全正确——“完全不同的实例”的定义听起来很关键。
  • 它可能不相关,但对我来说看起来不合适。您不应该锁定 (typeof(ClassA))。我通常锁定一个私有变量。请参阅此处了解更多详情msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.80).aspx

标签: c# .net multithreading


【解决方案1】:

问题很可能是共享资源 - 位图 - 不受代码示例中的锁保护。锁需要包装LockBitsUnlockBits 调用,以有效防止同时访问Bitmap 实例。

在这种情况下,我建议使用实际的 Bitmap 实例作为锁定对象,因为这是需要防止来自不同线程同时访问的内容。

仅当在静态方法中使用锁时才建议锁定typeof(ClassA)

请注意,锁是互斥锁,当一个线程获得锁时,其他线程将被挂起。如果大部分时间都花在锁中,那么拥有多个线程将不会或几乎没有并行化的好处。

如果发生异常,锁将通过锁结构的设计释放,而UnlockBits 方法通常不会被调用。如果可以抛出和捕获异常,我建议从 finally 块调用 UnlockBits 方法。像这样的:

private Bitmap _bitmap;
public void foo()
{
    lock (_bitmap)
    {
        BitmapData data;
        try
        {
            data = _bitmap.LockBits(area, ImageLockMOde.ReadOnly, pixelFormat);
            UseBitmapData(data);
        }
        finally
        {
            _bitmap.UnlockBits(data);
        }
    }
}

这个逻辑也可以封装在它自己的实现 IDisposable 接口的类中,允许使用强大的using 构造。

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多