C#3.0 - Monitor -Suggestions的应用

时间:2009-11-26 13:41:42

标签: c# delegates

为了理解Monitor我已经实现了以下代码。但我不确定代码是否是线程安全的。

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&lt;&gt ;, Predicate&lt;&gt;,lambdas如何改进我的代码?

3)我可以遵循的最佳模式是什么,以便使用发布者,观察者模式,我的意思是 我应该为...设计单独的课程吗? (i)自定义EventArgs (ii)听众 (iii)出版商 (iv)链接器 - (链接监听器,发布者,自定义EventArgs)?

3 个答案:

答案 0 :(得分:1)

Microsoft不建议使用lock(this)(也是Monitor.Wait(this))(请参阅MSDN on lock-Keyword)。

您可以使用单独的锁定对象,例如string变量或其他对象 - 这对于int之类的简单类型不起作用。

答案 1 :(得分:0)

这是家庭作业吗?反正...

1)快速查看之后,代码看起来对我来说是线程安全的,但是如此高度同步,以至于线程实际上不会同时执行任何工作。因此,对于这个代码,你也可以有一个带循环的线程。

2)现在不要担心,真正的改进不仅仅来自语法(在这种情况下,这主要是那些构造会带给你的东西)。

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

答案 2 :(得分:0)

您应该阅读以下有关锁定对象的文章(并按照文章顶部的评论中的链接):

http://haacked.com/archive/2005/04/12/NeverLockThis.aspx