2009-11-26 37 views
1

为了解监视器,我实现了下面的代码。但我不确定代码是否线程安全。C#3.0 - 监视器的应用 - 建议

namespace MonitorExample 
{ 
    public delegate void WaterLevelInformer(object sender,WaterLevelArgs e); 

    class WaterLevelListener 
    { 
     //listener will print information 
     // when WaterTank is reaching its empty level or full 
     public void ShowResult(object sender, WaterLevelArgs e) 
     { 
      Console.WriteLine("Water Level is :{0}", e.Level); 
     } 
    } 

    class WaterTank 
    { 
     //starting level is empty 
     static int level=0; 
     //capacity of the WaterTank is 2000 liters 
     const int capacity = 2000; 
     private WaterLevelListener lst = new WaterLevelListener(); 

     public event WaterLevelInformer levelHandler; 

     public WaterTank(WaterLevelListener lstn) 
     { 
      this.lst = lstn; 
      this.levelHandler +=new WaterLevelInformer(lst.ShowResult); 
     } 

     public void FillWater() 
     { 
      lock (this) 
      { 
       if (level >= capacity) 
       { 
        Monitor.Wait(this); 
       } 
       Console.WriteLine("....WaterTank is gettig filled..."); 
       for (int i = 100; i <= 2000; i+=100) 
       { 
        Console.WriteLine("Current Water Level {0}", i); 
        level = i; 
        Thread.Sleep(1000); 
        if (i == 1700) 
        { 
         WaterLevelInformation(level); 
         Thread.Sleep(1000); 
        } 
       } 

       Monitor.Pulse(this); 
      } 
     } 

     public void ConsumeWater() 
     { 
      lock (this) 
      { 
       if (level<=0) 
       { 
        Monitor.Wait(this); 
       } 
       Console.WriteLine("...Water is being consumed...."); 
       for (int i =2000; i >= 0; i -= 100) 
       { 
        Console.WriteLine("Current Water Level {0}", i); 
        Thread.Sleep(1000); 
        level = i; 
        if (i == 100) 
        { 
         WaterLevelInformation(i); 
         Thread.Sleep(1000); 
        } 
       } 

       Monitor.Pulse(this); 
      } 
     } 

     //WaterLevelInformation is used to raise the event 
     // When WaterTank reaching its empty level 
     //or WaterTank is full 
     public void WaterLevelInformation(int i) 
     { 
      if (levelHandler != null) 
      { 
       WaterLevelArgs waterArgs=new WaterLevelArgs(i); 
       levelHandler(this,waterArgs); 
      } 
     } 
    } 

    // WaterLevelArgs class stores the level of 
    // the water 
    public class WaterLevelArgs : EventArgs 
    { 
     public int Level 
     { 
      get; 
      set; 
     } 
     public WaterLevelArgs(int level) 
     { 
      Level = level; 
     } 
    } 

    class WaterLevelSimulator 
    { 

     static void Main() 
     { 
      WaterLevelListener lst = new WaterLevelListener(); 
      WaterTank tnk = new WaterTank(lst); 
      Thread thd1 = new Thread(new ThreadStart(tnk.ConsumeWater)); 
      Thread thd2 = new Thread(new ThreadStart(tnk.FillWater)); 
      thd1.Start(); 
      thd2.Start(); 
      Console.ReadKey(); 
     } 
    } 

} 

问题:

1)是上面的代码是线程安全的?

2)由于C#2.0和3.0引入了Action <>,Predicate <>,lambdas我该如何改进我的代码?

3)什么是最好的方式我可以为了使用出版商​​,Observer模式可循,我的意思是 我应该需要单独设计类 (I)定制的EventArgs (II)监听 (三)发行(iv)链接器 - (链接监听器,发布者,自定义EventArgs)?

回答

1

(见MSDN on lock-Keyword)。

你应该使用一个单独的锁定对象,如string变量或其他东西是一个对象 - 这不适用于简单的类型,如int什么的。

0

这功课吗?无论如何...

1)在快速查看它之后,代码看起来像线程安全的,但非常同步,线程实际上不会同时执行任何工作。因此,对于这个代码,你可以只有一个线程和一个循环。

2)现在不要担心,真正的改进不仅仅来自语法(在这种情况下,主要是那些构造会让你感到什么)。

3)我不清楚你在那里需要什么。

+0

当你认为某人想澄清某事是作业,那么这是作业。 – user215675 2009-11-26 13:56:50