2

我的印象是lock()会阻止多个线程同时访问一个对象。

但是,以下代码仍然经常抛出 InvalidOperationException(对象当前在别处使用):

lock (this)
{
    localCopy = (Bitmap)this.bm.Clone();
    int x, y;
    float pX = this.p.x;
    int width = localCopy.Width;
    x = (int)Math.Round((double)(pX * (float)width));
    if (x >= localCopy.Width) x = localCopy.Width - 1;
    y = (int)Math.Round((double)(this.p.y * (float)localCopy.Height));
    if (y >= localCopy.Height) y = localCopy.Height - 1;
    colourPixel = localCopy.GetPixel(x, y);
}

需要注意的一些事项:

  • 我拆分了计算x以隔离异常的原因。它似乎来自访问位图。
  • 我尝试创建位图的本地副本,但这只会导致相同的异常。我已经尝试过Clone()并创建一个新的位图。两者都不起作用。
  • 我已经尝试锁定this(如所见)和位图对象。两者都不起作用。

我是否试图以lock()我不应该的方式使用?我误解了它的目的吗?我怎样才能防止InvalidOperationExceptions?

4

2 回答 2

4

可能尝试使用对象来锁定目的而不是锁定“this”。

类级别变量

private static object syncRoot = new Object();

当你使用

lock (syncRoot)
{
....
}
于 2012-10-03T13:47:16.827 回答
1

我最终明白了这一点。我将锁移到位图属性的 getter/setter 方法中,并实现了“深拷贝”方法以尽快释放该属性。

private static object syncRoot = new Object();
private Bitmap _bm;
private Bitmap bm
{
    get
    {
        lock (syncRoot)
            return this._bm.DeepClone();
    }
    set
    {
        lock (syncRoot)
        {
            this._bm = value.DeepClone();
        }
    }
}

DeepClone() 扩展方法是从另一个问题的答案中抄袭而来的:

public static T DeepClone<T>(this T a)
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, a);
        stream.Position = 0;
        return (T)formatter.Deserialize(stream);
    }
}
于 2012-10-05T13:08:56.920 回答