Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизованное свойство, пытаюсь разобраться, появились вопросы 
:(
    Опции темы
DEER
Дата 20.6.2006, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



господа. возникла пара вопросов, касающихся синхронизации методов в C#.
точнее мне надо синхронизировать свойство (get и set как я понимаю) некоего объекта.
поиском пользовался кое что нашел полезное. (вот сообщение Domestic Cat'а)
Осталось упочнить детали.
итак.
суть моёй задачки такова
Цитата
Реализуйте 'синхронное' cвойство SharedRes типа Employee. Класс Employee  определен следующим образом
class Employee
{
  string fname
  string lname
  int Age
}
То есть,  свойство, самостоятельно заботящиеся о том, чтобы одновременно обращающиеся к нему потоки работали с ним корректно.

Правила такого обращения следуюшие: 
1. Записывать в одно время может только один поток, любой следующий 'писатель' должен ждать(блокироваться). 
2. Если один поток выполняет запись, то любой читатель должен ждать завершения 
этой записи. 
3. Пока происходит чтение свойства запись невозможна. 
4. Однако требуется избежать такой ситуации , когда запись невозможна изза сменяющих друг друга операций чтения. 
5. Любое количнеств читающих потоков могут читать одновременно. 

я пишу класс, у которого будет поле empl, например.
Создаю для него свойство
Код

 public Employee SharedRes
{
   get
   { //тут надо окончания записи в поле, читать могут несколько,
   }
   set
   { //тут надо ждать окончания чтения,  и окончания записи.
   }
}

вроде всё ясно, кроме правила № 4.
Далее приступаем к реализации. Domestic Cat использовал в примере поле private bool isBeerReady;. Если такой подход корректный, то добавлю в мой класс поля
Код

private bool isReading; // идет чтение
private bool isWriting; // идет запись

и теперь можно реализовать само свойство.
Код

 public Employee SharedRes
{
   get
   { //тут надо окончания записи в поле, читать могут несколько,
      lock(this.empl)
      {
          while(isWriting)
          {
              Monitor.Wait(this.empl); //что за монитор??? не понятно
          }
          isReading = true;
          Thread.sleep(5); //типа задержка
          return this.empl; // отдаем объект
          isReading = false;
      }
   }
   set
   { //тут надо ждать окончания чтения,  и окончания записи.
      lock(this.empl)
      {
          while(isWriting || isReading)
          {
              Monitor.Wait(this.empl); //что за монитор??? не понятно
          }
          isWriting = true;
          Thread.sleep(5); //типа задержка
          this.empl = value; //записываем объект
          isWriting = false;
      }
   }
}


скажите, правильно ли я понял использование lock, что надо указывать какой объект захватываем.
что такое Monitor и правильно ли я его использую.
как можно реализовать 4-е правило из задания. Я просто не до конца его понял.

заранее сенкс  

Это сообщение отредактировал(а) DEER - 20.6.2006, 10:35


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
ivashkanet
Дата 20.6.2006, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Пройдусь по коду  smile 
Цитата(DEER @  20.6.2006,  10:34 Найти цитируемый пост)
Thread.sleep(5); //типа задержка

Не должно быть у тебя задержки. Доместикс делал ее для емуляции процесса выпивания пива
Пока все. В остальном я пас   smile 
 
PM MAIL WWW ICQ   Вверх
DEER
Дата 20.6.2006, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



ivashkanet,  спасиба, но она должна быть по заданию, я просто не всё задание написал  smile  


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
mr.DUDA
Дата 20.6.2006, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



DEER, насчёт того, почему внутри блока lock используется Monitor - тут непонятка: если доступ к empl заблокирован для доступа из более чем одного потока (пресловутый lock), то зачем когда уже вошли внутрь lock - ещё и ждать монитором ? Всё равно при использовании lock более чем один reader или writer не сможет в одно и то же время работать с empl.

З.Ы. описываемая задача уже реализована средствами Framework - это класс ReaderWriterLock.   


--------------------
user posted image
PM MAIL WWW   Вверх
DEER
Дата 20.6.2006, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



mr.DUDA,   smile  точно! те сначала надо писать проверу а потом уже лочить..
Код

 public Employee SharedRes    
{    
   get    
   { //тут надо окончания записи в поле, читать могут несколько,    
          while(isWriting)    
          {    
              Monitor.Wait(this.empl); //что за монитор??? не понятно    
          }    
      lock(this.empl)    
      {    
          isReading = true;    
          Thread.sleep(5); //типа задержка    
          return this.empl; // отдаем объект    
          isReading = false;    
      }    
   }    
   set    
   { //тут надо ждать окончания чтения,  и окончания записи.    
          while(isWriting || isReading)    
          {    
              Monitor.Wait(this.empl); //что за монитор??? не понятно    
          }    
      lock(this.empl)    
      {    
          isWriting = true;    
          Thread.sleep(5); //типа задержка    
          this.empl = value; //записываем объект    
          isWriting = false;    
      }    
   }    
}

вот так получается?  smile 
на счет того что она решена... я это предполагал, но решить надо самому.это типа тестовое задание 


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
mr.DUDA
Дата 20.6.2006, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



А какой глубокий смысл делать ожидание, если вход в lock и так ожидает выхода из lock другого потока ?

З.Ы. оператор lock сам по себе реализован на основе Monitor-ов, между прочим smile 


--------------------
user posted image
PM MAIL WWW   Вверх
DEER
Дата 20.6.2006, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



ну вот я и спрашиваю. правильно я их использую или нет?

Добавлено @ 16:53 
тут посоветовали вообще без локов делать... 


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
Аленка
Дата 21.6.2006, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



А как без локов получилось? Если получилось?

Код

while(isWriting || isReading)     
          {     
              Monitor.Wait(this.empl); //что за монитор??? не понятно     
          }     
      lock(this.empl)     
     

так не получится, lock()-это тоже самое что Monitor.Enter() +Monitor.Exit(). Т.е. надо сначала сделать enter, затем wait, exit.

 4 пункт- это классическая проблема writers-readers. Может решиться введением дополнительных переменных, считающих количество ожидающих writerов и readerов.
Проверка такая: если readerов больше нет, и есть writer, то запускаем его. Пока не закончатся smile


 
PM   Вверх
DEER
Дата 21.6.2006, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



Цитата
А как без локов получилось? Если получилось?

Совсем без локов не получилось...
кое что похожее на правду получилось как раз с Enter и Exit...
так и не понял почему правда....
при исп Локов вылетали екзепшены разнообразные, а сейчас по крайней мере что то делает....

Добавлено @ 11:12 
выгладит вот так
Код

    public class MyClass
    {
        CEmployee empl;
        public MyClass()
        {
            empl = new CEmployee();
            isReading = false;
            isWriting = false;
            isWriteWaiting = false;
        }
        private bool isReading;// true, если идёт чтение
        private bool isWriting;// true, если идет запись
        private bool isWriteWaiting;// true, если есть в очереди на запись

    //    [Synchronization]
        public CEmployee SharedRes
        {
            get
            {//тут надо ждать окончания записи, читать могут несколько но приоритет у записи
                try
                {
                    while(isWriting||isWriteWaiting)
                    { 
                        Monitor.Wait(this.empl, 5);//ждем пока освободится объект 
                    }
                    Monitor.Enter(this.empl);
                    isReading = true;
                    Thread.Sleep(10);
                    isReading = false;
                    Monitor.Exit(this.empl);
                    return empl;
                }
                catch(Exception ee)
                {
                    return empl;
                }
            }
            set
            {//тут надо ждать окончания чтения, и окончания записи
                try
                {
                    isWriteWaiting = true;
                    while(isWriting||isReading)
                    { 
                        Monitor.Wait(this.empl, 5);//ждем пока освободится объект 
                    }
                    Monitor.Enter(this.empl);
                    isWriteWaiting = false;
                    isWriting = true;
                    Thread.Sleep(10);
                    empl.Name = value.Name;
//                    Thread.Sleep(10);
                    empl.LastName = value.LastName;
//                    Thread.Sleep(10);
                    empl.Age = value.Age;
//                    Thread.Sleep(10);
                    isWriting = false;
                    isWriteWaiting = false;
                    Monitor.Exit(this.empl);
                }
                catch(Exception ee)
                {
                    //
                }            
            }
        }
    }

 


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
Аленка
Дата 21.6.2006, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



А как тестируешь?

Код

WorkerClass w = new WorkerClass();
...
Thread workerThread = new Thread(new ThreadStart(w.DoSomeWork));


 что передаешь вместо DoSomeWork?  

Это сообщение отредактировал(а) Аленка - 21.6.2006, 11:31
PM   Вверх
DEER
Дата 21.6.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



тест не очень получился...
Код

        private MyClass m;
        public void Writer()
        {
            for(int i=0; i<50; i++)
            {
                listBox1.Items.Add("пишу данные");
                m.SharedRes = new CEmployee("Один"+i.ToString(), "Одинович"+i.ToString(), i);
            }
        }
        public void Reader()
        {
            for(int i =0; i<50; i++)
            {
                listBox1.Items.Add("читаю данные");
                CEmployee tmpEmpl = m.SharedRes;
                listBox1.Items.Add(tmpEmpl.Name+"-"+tmpEmpl.LastName+"-"+tmpEmpl.Age.ToString());
            }
        }
        private void button1_Click(object sender, System.EventArgs e)
        {
            m = new MyClass();
            //потоки писатели
            Thread tw1 = new Thread(new ThreadStart(Writer));
            Thread tw2 = new Thread(new ThreadStart(Writer));
            //потоки - читатели
            Thread tr1 = new Thread(new ThreadStart(Reader));
            Thread tr2 = new Thread(new ThreadStart(Reader));
            tw1.Start();
            tw2.Start();
            tr1.Start();
            tr2.Start();
        }
 


--------------------
 
PM MAIL WWW ICQ MSN   Вверх
YoungMan
Дата 13.7.2006, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



Если использовать код, приведенный DEER-ом, то получим, что "читатели" будут выводить "скомканные" данные о сотруднике:
Один1-Одинович1-1
Один2-Одинович1-1
Один2-Одинович2-1
Один2-Одинович2-1
Один2-Одинович2-2
Один3-Одинович2-2
Один3-Одинович3-2
Один3-Одинович3-3
...
(текст функции writer опущен)

Вопрос: как от этого избавиться? 
PM MAIL   Вверх
YoungMan
Дата 13.7.2006, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



и еще вопрос, почему если убрать конструкцию try-catch появляются ошибки типа:
Код

An unhandled exception of type 'System.Threading.SynchronizationLockException' occurred in mscorlib.dll
Additional information: Object synchronization method was called from an unsynchronized block of code. 

в месте проверки условия циклов: 
Код

while(isWriting||isWriteWaiting)
и 
Код

while(isWriting||isReading)
 
PM MAIL   Вверх
YoungMan
Дата 14.7.2006, 05:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



На мой взгляд класс MyClass должен выглядеть вот так:
Код

public class MyClass
    {
        Employee empl;
        public MyClass()
        {
            empl = new Employee();
            isReading = false;
            isWriting = false;
            isWriteWaiting = false;
        }
        private bool isReading;// true, если идёт чтение
        private bool isWriting;// true, если идет запись
        private bool isWriteWaiting;// true, если есть в очереди на запись

        private static object somePrivateStaticObject = new Object();

        public Employee SharedRes
        {
            get
            {//тут надо ждать окончания записи, читать могут несколько но приоритет у записи
                    Employee tEmpl;
                    
                        do
                        { 
                            Monitor.TryEnter(this.empl, 10);
                            //ждем пока освободится объект 
                        }
                        while(isWriting||isWriteWaiting);
                        isReading = true;
                        tEmpl = this.empl;
                        Thread.Sleep(10);
                        isReading = false;
                        Monitor.Exit(this.empl);

                    return tEmpl;
            }
            set
            {//тут надо ждать окончания чтения, и окончания записи
                        isWriteWaiting = true;
                        do
                        { 
                            Monitor.TryEnter(this.empl, 10);
                            //ждем пока освободится объект 
                        }
                        while(isWriting||isReading);
                        isWriting = true;
                        isWriteWaiting = false;
                        Thread.Sleep(10);
                        empl.fname = value.fname;
                        Thread.Sleep(10);
                        empl.lname = value.lname;
                        Thread.Sleep(10);
                        empl.Age = value.Age;
                        Thread.Sleep(10);
                        isWriting = false;
                        Monitor.Exit(this.empl);
            }
        }
    }
 
PM MAIL   Вверх
Аленка
Дата 14.7.2006, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Цитата(YoungMan @ 13.7.2006,  22:01)
и еще вопрос, почему если убрать конструкцию try-catch появляются ошибки типа:
Код

An unhandled exception of type 'System.Threading.SynchronizationLockException' occurred in mscorlib.dll
Additional information: Object synchronization method was called from an unsynchronized block of code. 


Потому и появляются, что Object synchronization method was called from an unsynchronized block of code.
 try catch похоже просто позволяет избежать потенциальных ошибок при обращении к уже используемому монитору. Синхронизировать надо использование монитора.
И скомканные данные получаются, потому что нет синхронизации.   

Это сообщение отредактировал(а) Аленка - 14.7.2006, 20:04
PM   Вверх
YoungMan
Дата 15.7.2006, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



Это я уже понял.
Решая данную задачу через ReaderWriterLock класс, у сеня получилось так:
    
Код

public class MyClass
    {        
        #region Конструктор
        /// <summary>
        /// Конструктор класса
        /// </summary>
        public MyClass()
        {
            oEmpl = new Employee();
            rnd = new Random();
            rwl = new ReaderWriterLock();
        }
        #endregion

        #region Поля класса
        /// <summary>
        /// Объект класса сотрудник
        /// </summary>
        private Employee oEmpl = null;
        /// <summary>
        /// Определяет блокировку с возможностью одновременного множественного чтения и одничной записи
        /// </summary>
        public static ReaderWriterLock rwl;
        /// <summary>
        /// Реализация случайной величины
        /// </summary>
        private Random rnd;
        #endregion

        #region Открытые свойства класса
        /// <summary>
        /// "Синхронизированное"  свойство чтения(записи) информации о сотруднике
        /// </summary>
        public Employee SharedRes
        {
            get
            {
                try
                {
                    rwl.AcquireReaderLock(1000);
                    try
                    {
                        Employee tEmpl;
                        tEmpl = this.oEmpl;
                        Thread.Sleep(rnd.Next(20));
                        return tEmpl;
                    }
                    finally
                    {
                        rwl.ReleaseReaderLock();
                    }
                }
                catch(Exception)
                {
                    return null;
                }

            }
            set
            {
                try
                {
                    rwl.AcquireWriterLock(1000);
                    try
                    {
                        this.oEmpl.fname = value.fname;
                        Thread.Sleep(rnd.Next(20));
                        this.oEmpl.lname = value.lname;
                        Thread.Sleep(rnd.Next(20));
                        this.oEmpl.Age = value.Age;
                        Thread.Sleep(rnd.Next(20));
                    }
                    finally
                    {
                        rwl.ReleaseWriterLock();
                    }
                }
                catch(Exception)
                {
                }

            }
        }

        #endregion
    }

Но у меня все равно иногда проскакивает "скомканный вывод", чего быть по идее не долно.
класс вызова:
Код

    public class ThreadApp : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button btnStrStp;
        private System.Windows.Forms.ListBox listBox;

        /// <summary>
        /// Флаг запуска(остановки) приложения
        /// </summary>
        private bool bStrStp;
        /// <summary>
        /// Переменная класса чтения/записи
        /// </summary>
        private MyClass m;
        /// <summary>
        /// Количиство "писателей"
        /// </summary>
        private static int iWriter;
        /// <summary>
        /// Количиство "читателей"
        /// </summary>
        private static int iReader;
        /// <summary>
        /// Общее количетво потоков
        /// </summary>
        int iNemberOfTreads = 12;        
        /// <summary>
        /// Массив потоков
        /// </summary>
        Thread[] tPool;

        static ReaderWriterLock rwl = new ReaderWriterLock();

        private System.ComponentModel.Container components = null;

        public ThreadApp()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            CustomInitialize();
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.listBox = new System.Windows.Forms.ListBox();
            this.btnStrStp = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // listBox
            // 
            this.listBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
            this.listBox.Location = new System.Drawing.Point(8, 0);
            this.listBox.Name = "listBox";
            this.listBox.Size = new System.Drawing.Size(304, 329);
            this.listBox.TabIndex = 0;
            // 
            // btnStrStp
            // 
            this.btnStrStp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnStrStp.Location = new System.Drawing.Point(320, 8);
            this.btnStrStp.Name = "btnStrStp";
            this.btnStrStp.Size = new System.Drawing.Size(96, 24);
            this.btnStrStp.TabIndex = 1;
            this.btnStrStp.Text = "Пуск";
            this.btnStrStp.Click += new System.EventHandler(this.btnStrStp_Click);
            // 
            // ThreadApp
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(416, 334);
            this.Controls.Add(this.btnStrStp);
            this.Controls.Add(this.listBox);
            this.Name = "ThreadApp";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// Точка входа приложения
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new ThreadApp());
        }
        
        /// <summary>
        /// Обработка событий нажатия кнопки (Запуск/Остановка приложения)
        /// </summary>
        /// <param name="sender">Ресурс события</param>
        /// <param name="e">Информация о событии</param>
        private void btnStrStp_Click(object sender, System.EventArgs e)
        {
            //Изменение значения флага запуска(остановки)
            bStrStp = !bStrStp;

            // Запуск / остановка приложения
            if (!bStrStp)
            {
                for(int i=0; i<iNemberOfTreads; i++)
                {
                    tPool[i].Join();
                }                
                btnStrStp.Text = "Пуск";
            }
            else
            {
                Start();
                btnStrStp.Text = "Остановка";
            }
            
        }

        /// <summary>
        /// Определение пользовательских переменных
        /// </summary>
        private void CustomInitialize()
        {
            bStrStp = false;
            m = new MyClass();
            iWriter = 0;
            iReader = 0;
            tPool = new Thread[iNemberOfTreads];

        }
        /// <summary>
        /// Функция запуска приложения
        /// </summary>
        private void Start()
        {
            //Формирование потоков чтения/записи
            for(int i = 0; i<iNemberOfTreads; i++)
            {
                if (i%6 == 0)
                    //поток "писатель"
                    tPool[i] = new Thread(new ThreadStart(Write));
                else
                    //поток "читатель"
                    tPool[i] = new Thread(new ThreadStart(Read));
                tPool[i].Name = new String(Convert.ToChar(i + 65), 1);
                tPool[i].Start();
                Thread.Sleep(10);
            }
        }
        /// <summary>
        /// Функция записи данных о сотруднике
        /// </summary>
        private void Write()
        {
            int iWriterIndex = ++iWriter;
            int index = 0;
            while(bStrStp)
            {
                string sFName = "Имя_" + iWriterIndex.ToString() + "_" + (++index).ToString();
                string sLName = "Фамилия_"+ iWriterIndex.ToString() + "_" + index.ToString();
                int iAge = iWriterIndex*1000 + index;
                m.SharedRes = new Employee(sFName, sLName, iAge);
                listBox.Items.Add("Writer (" + iWriterIndex + "): Выполнен " + index.ToString());
            }
        }
        /// <summary>
        /// Функция чтения данных о сотруднике
        /// </summary>
        private void Read()
        {
            int iReaderIndex = ++iReader;
            int index = 0;
            while(bStrStp)
            {
                ++index;
                try
                {
                    rwl.AcquireReaderLock(1000);
                    try
                    {
                        Employee oEmpl = m.SharedRes;
                        if (!(oEmpl == null))
                            listBox.Items.Add("Reader (" + iReaderIndex + "|" + index.ToString() + "): " + oEmpl.fname + "*" + oEmpl.lname + "*" + oEmpl.Age.ToString());
                    }
                    finally
                    {
                        rwl.ReleaseReaderLock();            
                    }    
                }
                catch(Exception)
                {
                }
            }
        }

    }

Не подскажите что я не правильно делаю? 
PM MAIL   Вверх
YoungMan
Дата 15.7.2006, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



сори, вот новый новый класс вызова:
Код

    public class ThreadApp : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button btnStrStp;
        private System.Windows.Forms.ListBox listBox;

        /// <summary>
        /// Флаг запуска(остановки) приложения
        /// </summary>
        private bool bStrStp;
        /// <summary>
        /// Переменная класса чтения/записи
        /// </summary>
        private MyClass m;
        /// <summary>
        /// Количиство "писателей"
        /// </summary>
        private static int iWriter;
        /// <summary>
        /// Количиство "читателей"
        /// </summary>
        private static int iReader;
        /// <summary>
        /// Общее количетво потоков
        /// </summary>
        int iNemberOfTreads = 12;        
        /// <summary>
        /// Массив потоков
        /// </summary>
        Thread[] tPool;

        private System.ComponentModel.Container components = null;

        public ThreadApp()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            CustomInitialize();
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.listBox = new System.Windows.Forms.ListBox();
            this.btnStrStp = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // listBox
            // 
            this.listBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
            this.listBox.Location = new System.Drawing.Point(8, 0);
            this.listBox.Name = "listBox";
            this.listBox.Size = new System.Drawing.Size(304, 329);
            this.listBox.TabIndex = 0;
            // 
            // btnStrStp
            // 
            this.btnStrStp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnStrStp.Location = new System.Drawing.Point(320, 8);
            this.btnStrStp.Name = "btnStrStp";
            this.btnStrStp.Size = new System.Drawing.Size(96, 24);
            this.btnStrStp.TabIndex = 1;
            this.btnStrStp.Text = "Пуск";
            this.btnStrStp.Click += new System.EventHandler(this.btnStrStp_Click);
            // 
            // ThreadApp
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(416, 334);
            this.Controls.Add(this.btnStrStp);
            this.Controls.Add(this.listBox);
            this.Name = "ThreadApp";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// Точка входа приложения
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new ThreadApp());
        }
        
        /// <summary>
        /// Обработка событий нажатия кнопки (Запуск/Остановка приложения)
        /// </summary>
        /// <param name="sender">Ресурс события</param>
        /// <param name="e">Информация о событии</param>
        private void btnStrStp_Click(object sender, System.EventArgs e)
        {
            //Изменение значения флага запуска(остановки)
            bStrStp = !bStrStp;

            // Запуск / остановка приложения
            if (!bStrStp)
            {
                for(int i=0; i<iNemberOfTreads; i++)
                {
                    tPool[i].Join();
                }                
                btnStrStp.Text = "Пуск";
            }
            else
            {
                Start();
                btnStrStp.Text = "Остановка";
            }
            
        }

        /// <summary>
        /// Определение пользовательских переменных
        /// </summary>
        private void CustomInitialize()
        {
            bStrStp = false;
            m = new MyClass();
            iWriter = 0;
            iReader = 0;
            tPool = new Thread[iNemberOfTreads];

        }
        /// <summary>
        /// Функция запуска приложения
        /// </summary>
        private void Start()
        {
            //Формирование потоков чтения/записи
            for(int i = 0; i<iNemberOfTreads; i++)
            {
                if (i%6 == 0)
                    //поток "писатель"
                    tPool[i] = new Thread(new ThreadStart(Write));
                else
                    //поток "читатель"
                    tPool[i] = new Thread(new ThreadStart(Read));
                tPool[i].Name = new String(Convert.ToChar(i + 65), 1);
                tPool[i].Start();
                Thread.Sleep(10);
            }
        }
        /// <summary>
        /// Функция записи данных о сотруднике
        /// </summary>
        private void Write()
        {
            int iWriterIndex = ++iWriter;
            int index = 0;
            while(bStrStp)
            {
                string sFName = "Имя_" + iWriterIndex.ToString() + "_" + (++index).ToString();
                string sLName = "Фамилия_"+ iWriterIndex.ToString() + "_" + index.ToString();
                int iAge = iWriterIndex*1000 + index;
                m.SharedRes = new Employee(sFName, sLName, iAge);
                listBox.Items.Add("Writer (" + iWriterIndex + "): Выполнен " + index.ToString());
            }
        }
        /// <summary>
        /// Функция чтения данных о сотруднике
        /// </summary>
        private void Read()
        {
            int iReaderIndex = ++iReader;
            int index = 0;
            while(bStrStp)
            {
                ++index;
                Employee oEmpl = m.SharedRes;
                if (!(oEmpl == null))
                    listBox.Items.Add("Reader (" + iReaderIndex + "|" + index.ToString() + "): " + oEmpl.fname + "*" + oEmpl.lname + "*" + oEmpl.Age.ToString());
            }
        }

    }


Но вопрос остается "скомканности" остается  smile  
PM MAIL   Вверх
YoungMan
Дата 15.7.2006, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



 smile А в таком варианте все нормально:
Код

public class MyClass
    {        
        #region Конструктор
        /// <summary>
        /// Конструктор класса
        /// </summary>
        public MyClass()
        {
            oEmpl = new Employee();
            rnd = new Random();
            rwl = new ReaderWriterLock();
        }
        #endregion

        #region Поля класса
        /// <summary>
        /// Объект класса сотрудник
        /// </summary>
        private Employee oEmpl = null;
        /// <summary>
        /// Определяет блокировку с возможностью одновременного множественного чтения и одничной записи
        /// </summary>
        private static ReaderWriterLock rwl;
        /// <summary>
        /// Реализация случайной величины
        /// </summary>
        private Random rnd;
        #endregion

        #region Открытые свойства класса
        /// <summary>
        /// "Синхронизированное"  свойство чтения(записи) информации о сотруднике
        /// </summary>
        public Employee SharedRes
        {
            get
            {
                //чтенение данных о сотруднике
                try
                {
                    rwl.AcquireReaderLock(1000);
                    try
                    {
                        //Создание копии объета сотрудника
                        Employee tEmpl = new Employee();
                        //Чтение имени
                        tEmpl.fname = this.oEmpl.fname;
                        Thread.Sleep(rnd.Next(100));
                        //Чтение фамилии
                        tEmpl.lname = this.oEmpl.lname;
                        Thread.Sleep(rnd.Next(100));
                        //Чтение возраста
                        tEmpl.Age = this.oEmpl.Age;
                        Thread.Sleep(rnd.Next(100));
                        return tEmpl;
                    }
                    finally
                    {
                        rwl.ReleaseReaderLock();
                    }
                }
                catch(Exception)
                {
                    return null;
                }

            }
            set
            {
                //запись данных о сотруднике
                try
                {
                    rwl.AcquireWriterLock(1000);
                    try
                    {
                        //Запись имени сотрудника
                        this.oEmpl.fname = value.fname;
                        Thread.Sleep(rnd.Next(500));
                        //Запись фамилии сотрудника
                        this.oEmpl.lname = value.lname;
                        Thread.Sleep(rnd.Next(500));
                        //Запись возраста сотрудника
                        this.oEmpl.Age = value.Age;
                        Thread.Sleep(rnd.Next(500));
                    }
                    finally
                    {
                        rwl.ReleaseWriterLock();
                    }
                }
                catch(Exception)
                {
                }

            }
        }

        #endregion
    }
 
PM MAIL   Вверх
Аленка
Дата 17.7.2006, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Ну ты же сам наверно все понимаешь smile  (Это я насчет скомканности)
Ты увеличил время, через которое методы обращаются к данным, поэтому, возможно, они и успевают закончить работу, не прерываясь другими методами.
 
PM   Вверх
YoungMan
Дата 17.7.2006, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 13.7.2006

Репутация: нет
Всего: нет



Но время на запись (в среднем) значительно больше времени чтения чтения, т.е. больше "читателей" могут влезть.

Или я не правильно понимаю?

Может подскажешь тогда smile. 
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0750 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.