简体   繁体   English

C#为什么我的锁声明挂了?

[英]C# Why is my lock statement hanging?

I have followed some tutorials on how to create custem event accessors. 我已经学习了一些关于如何创建custem事件访问器的教程。 This is the code I have: 这是我的代码:

event ControlNameChangeHandler IProcessBlock.OnControlNameChanged
{
    add
    {
        lock (ControlNameChanged)
        {
            ControlNameChanged += value;
        }
    }
    remove
    {
        lock (ControlNameChanged)
        {
            ControlNameChanged -= value;
        }
    }
}

At the moment the code reaches lock(ControlNameChanged) in the add statament, nothing happens. 目前代码在add statament中达到lock(ControlNameChanged) ,没有任何反应。 The code doesn't run any further. 代码不再运行。 However my application is still working. 但是我的申请仍然有效。 It doesn't freeze or something. 它不冻结或什么的。

What goes wrong? 出了什么问题?

Somehow, someone else holds a lock. 不知何故,其他人持有锁。 You shouldn't use multicast delegate instances or events for locking, and you shouldn't use public members either, because you cannot control who is locking and when. 您不应该使用多播委托实例或事件来进行锁定,也不应该使用公共成员,因为您无法控制谁锁定以及何时锁定。

Therefore I'd use a separate locking object like this: 因此我会使用这样的单独锁定对象:

private readonly object controlNameChangedSync = new object();

event ControlNameChangeHandler IProcessBlock.OnControlNameChanged
{
  add
  {
    lock (controlNameChangedSync)
    {
      ControlNameChanged += value;
    }
  }
  remove
  {
    lock (controlNameChangedSync)
    {
      ControlNameChanged -= value;
    }
  }
}

Note: the reference to the event changes when doing a += or -= on the delegate. 注意:在委托上执行+=-=时,对事件的引用会发生更改。

Your code is equivalent to 你的代码相当于

event ControlNameChangeHandler IProcessBlock.OnControlNameChanged {
    add {
        try {
            Monitor.Enter(ControlNameChanged);
            ControlNameChanged = ControlNameChanged + value;
        }
        finally {
            Monitor.Exit(ControlNameChanged);
        }
    } 
    remove { 
        try {
            Monitor.Enter(ControlNameChanged);
            ControlNameChanged = ControlNameChanged - value;
        }
        finally {
            Monitor.Exit(ControlNameChanged);
        }
    } 
}

Note that the object you Exit is different from the one you enter. 请注意,您退出的对象与您输入的对象不同。 This means you have one lock taken which is never released, and one lock is released but never taken. 这意味着你有一个锁从未被释放,一个锁被释放但从未被取走。 You should change your code into this: 您应该将代码更改为:

private object padlock = new object();
event ControlNameChangeHandler IProcessBlock.OnControlNameChanged {
    add {
        lock (padlock) {
            ControlNameChanged += value;
        }
    } 
    remove { 
        lock (padlock) {
            ControlNameChanged -= value;
        }
    } 
}

The += and -= operators change the delegate. +=-=运算符更改委托。 So your Add and Remove methods are locking on different objects each time, and you have no synchronization at all. 因此,每次添加和删除方法都锁定在不同的对象上,并且根本没有同步。

Now this wouldn't explain blocking but your question is not very clear on what actually happens. 现在这不能解释阻塞,但你的问题并不是很清楚实际发生了什么。 I would expect the program to execute 'normally' with the possibility of race-conditions. 我希望程序能够“正常”执行并具备竞争条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM