从一个公共类调用另一个公共类的静态参数

4

我正在尝试编写一个多线程应用程序,并且需要使用Monitoer.Enter/Exit/Wait/Pulse。我已经创建了一个Lock对象并在其自己的类中使用它,如下所示:

public partial class domain 
    /*I dont sure this is the good practice way to mange DDD Layers (if anybody have a comment about it)*/
{

   Public class Peer2PeerCom
   {
    public static readonly object locker = new object();
    //other stuff here
    //...
    //somwhere here
    Monitor.Pulse(locker);
   }   
}

在另一个班级中,我想/需要像那样使用储物柜。
public class Control
{
public domain.Peer2PeerCom Dom_P2PCom = new domain.Peer2PeerCom();
internal void connection ( int port , string IpAdress)
 {
  Monitor.Enter(Dom_P2PCom.locker);
  //do stuff here
  Monitor.wait(Dom_P2PCom.locker);
  //..
  Monitor.Exit(Dom_P2PCom.locker);
 }
}

但是当我尝试时,我无法识别locker,我认为这是因为它是static,但我不知道如何在不使整个类变为静态的情况下进行更正。


2
你是不是指的是 Peer2PeerCom.locker - Sayse
1个回答

3

您正在尝试通过引用访问静态成员。在C#中这是不起作用的,幸运的是 - 如果允许,在Java中可能会导致非常误导人的代码。

相反,您应该使用类的名称来访问静态成员:

lock (domain.Peer2PeerCom.locker)
{
    ...
    // This should probably be in a while loop...
    Monitor.Wait(domain.Peer2PeerCom.locker);
}

我在你提供的代码中使用了lock而不是显式地调用Monitor.EnterMonitor.Exit。这种方法更符合惯用法,而且更容易正确使用。如果在进入锁之后的代码中有任何异常,则会导致锁无法释放,造成“泄漏”。
一般来说,我强烈建议不要使用公共静态字段作为共享锁,因为这会使得很难理解是哪个部分正在使用该锁。如果将锁设置为类内私有,则更容易进行推理。(我还建议不要使用公共字段,以及在类名中使用下划线、没有明确原因却嵌套的类和名为domain的类名。)

谢谢你提供完整的答案和好的建议,但我还有几个问题: 1)为什么我要将Monitor.wait放在一个while循环中? 2)你所说的监视器“泄露”是什么意思? 3)我同意关于公共静态的观点,但我应该如何做? - LordTitiKaka
@LordTitiKaka:1)通常情况下,只有在特定条件不满足时才需要等待;通常情况下,您希望循环直到满足条件为止;2)这意味着即使您不想要它,线程仍将“拥有”监视器,可能导致死锁或至少是不希望的行为;3)我们没有足够的信息来了解您试图实现什么,以提供替代方案。您可能需要提出一个新问题,并提供更多信息。 - Jon Skeet
  1. 如果我没记错的话,Monitor.Wait会阻塞线程直到Monitor.Pulse在某处触发,对吗?我的意思是,如果我没错的话,While循环会被阻塞。
  2. 你说得对,我没有考虑到这一点,我会改正我的方法 :)
- LordTitiKaka
@LordTitiKaka:是的,除非出现虚假唤醒,即Monitor.Wait在没有脉冲的情况下返回。我不确定这是否仍然是一个问题,但通常如果您更多地考虑设计,您会发现有一个条件是明智的检查。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接