C# 事件死锁

C# 事件死锁,c#,C#,我明白了: object locker = new object(); // EDIT: sorry, omitted for simplicity. lock(this) is not the source of the problem. private Something property; public event SomethingHandler PropertyChanged; public Something Property { get { lock (l

我明白了:

object locker = new object(); // EDIT: sorry, omitted for simplicity. lock(this) is not the source of the problem.
private Something property;
public event SomethingHandler PropertyChanged;

public Something Property
{
    get {
        lock (locker) {
            return property;
        }
    }

    set {
        lock (locker) {
            property = value;
            PropertyChanged();
        }
    }
}
然后这个:

MyClass.PropertyChanged += () =>
{
    DoSomethingWithNewValue(MyClass.Property);
};
出于显而易见的原因,这会导致死锁。 处理这种情况的正确方法是什么

我可以将PropertyChanged()放在锁{}之后 或者从get{}中移除锁,或者将新值传递给处理程序,
但这一切看起来都有点不对劲。

在锁定之后调度事件,否则永远无法保证事件处理代码(不受您控制)不会尝试读取属性并导致死锁,即使您锁定了私有对象。

对我来说似乎不是显而易见的原因!
根本帮不了你,因为副作用会在同一个线程上运行。您真的遇到了死锁还是堆栈溢出?
DoSomethingWithNewValue
MyClass.Property
做了什么?如果我理解正确,事件会在锁块内部引发,然后订阅该事件的代码尝试再次(通过getter)确认锁,导致锁永远等待。从getter中移除锁或将PropertyChanged()移到锁{}修复了它。@user3360080:因为您没有发布代码,这会重现问题,所以很难给您答案。发布真实代码。从引发事件的同一线程读取属性值不会导致死锁。OP代码示例没有告诉我们,该属性是从另一个线程读取的。我想我误解了锁的工作方式。从锁定块中调用的代码内部再次锁定可以吗?同一线程重新进入锁定也可以,因此通常这不应该是问题,但是如果事件处理程序中有其他同步代码,这种构造可能会导致非常微妙的错误。没有理由在锁里放零钱。我不会。@Gusdor:你检查过了吗?;)@斯彭德:不。我一直都是这样理解的。我认为这是一个很琐碎的知识,比如int32有多大,但唉,我错得太离谱了。我一直非常小心地避免再次进入。没有解释为什么这个例子会导致死锁。事件处理程序与初始锁位于同一线程上。