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

时间:2010-01-08 10:25:36

标签: c# .net locking

我已经学习了一些关于如何创建custem事件访问器的教程。这是我的代码:

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

当代码在添加元素中达到lock(ControlNameChanged)时,没有任何反应。代码不再运行。但是我的申请仍然有效。它不冻结或什么的。

出了什么问题?

3 个答案:

答案 0 :(得分:13)

不知何故,其他人持有锁。您不应该使用多播委托实例或事件来进行锁定,也不应该使用公共成员,因为您无法控制谁在锁定以及何时锁定。

因此我会使用一个单独的锁定对象:

private readonly object controlNameChangedSync = new object();

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

注意:在委托上执行+=-=时,对事件的引用会发生变化。

答案 1 :(得分:8)

您的代码等同于

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);
        }
    } 
}

请注意,您退出的对象与您输入的对象不同。这意味着你有一个锁从未被释放,一个锁被释放但从未被取走。您应该将代码更改为:

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

答案 2 :(得分:4)

+=-=运算符更改委托。因此,每次添加和删除方法都锁定在不同的对象上,并且根本没有同步。

现在这不能解释阻塞,但你的问题并不是很清楚实际发生了什么。我希望程序能够“正常”执行并具有竞争条件。