2009-11-26 43 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