问题描述
我的印象是 lock()
会阻止多个线程同时访问一个对象.
I was under the impression that lock()
would prevent multiple threads from accessing an object simultaneously.
但是,以下代码仍然经常抛出 InvalidOperationException(对象当前正在其他地方使用):
But, an InvalidOperationException (Object is currently in use elsewhere) is still frequently thrown by the following code:
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()
ing 并创建一个新的位图.两者都不起作用. - 我尝试锁定
this
(如所见)和位图对象.两者都不起作用.
- I split up the calculation of
x
to isolate the cause of the exception. It appears to come from accessing the bitmap. - I tried creating a local copy of the bitmap, but this just causes the same exception. I've tried
Clone()
ing and creating a new Bitmap. Neither works. - I've tried locking on
this
(as seen) and on the bitmap object. Neither works.
我是否试图以一种不应该的方式使用 lock()
?我误解了它的目的吗?如何防止 InvalidOperationException
s?
Am I trying to use lock()
in a way I'm not supposed to? Have I misunderstood it's purpose? How can I prevent InvalidOperationException
s?
推荐答案
我最终找到了这个问题的根源.我把锁移到了位图属性的getter/setter方法中,并实现了一个深拷贝"的方法来尽快释放这个属性.
I eventually got to the bottom of this. I moved the locks into the getter / setter methods of the bitmap property and implemented a "deep copy" method to free up the property as soon as possible.
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() 扩展方法来自另一个问题的答案:
The DeepClone() extension method was cribbed from an answer to another question:
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);
}
}
这篇关于锁定不会阻止 InvalidOperationException:对象当前正在其他地方使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!