C # 3.0 - Применение Monitor -Suggestions - PullRequest
1 голос
/ 26 ноября 2009

Для понимания монитора я реализовал следующий код. Но я не уверен, является ли этот код безопасным для потоков.

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 <>, лямбды, как я могу улучшить свой код?

3) Какой лучший шаблон я могу использовать, чтобы использовать издателя, шаблон наблюдателя, я имею в виду Должен ли я разработать отдельный класс для (i) пользовательские EventArgs (ii) Слушатели (iii) издатели (iv) компоновщик - (линкинг слушателей, издателей, пользовательских EventArgs)?

Ответы [ 3 ]

1 голос
/ 26 ноября 2009

Использование lock(this) (также Monitor.Wait(this)) не рекомендуется Microsoft (см. MSDN для lock -Keyword ).

Вы можете использовать отдельный объект блокировки, например переменную string или что-то еще, что является объектом - это не будет работать для простых типов, таких как int или что-то еще.

0 голосов
/ 26 ноября 2009

Вам следует прочитать следующую статью о блокировке объектов (и перейти по ссылке в комментарии в верхней части статьи):

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

0 голосов
/ 26 ноября 2009

Это домашняя работа? В любом случае ...

1) После быстрого просмотра код выглядит для меня поточно-ориентированным, но настолько сильно синхронизированным, что потоки фактически не выполняют никакой работы одновременно. Следовательно, для этого кода вы могли бы также иметь один поток с циклом.

2) Не беспокойтесь об этом сейчас, настоящее улучшение происходит не только за счет синтаксиса (и в этом случае это в основном то, что эти конструкции могли бы получить).

3) Мне не понятно, что вам там нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...