2015-02-25 5 views
2

Вы можете подумать, что класс странный, но он образовательный, поэтому я должен сделать это таким образом.Как я могу заблокировать метод до тех пор, пока счетчик объектов не достигнет> 0?

class petriPool { 
    private int[] nodes = new int[3]; 
    private int counter; 

    private readonly object _lock = new object(); 

    public petriPool (int n, int m) { 
     this.nodes[0] = n; 
     this.nodes[1] = 0; 
     this.nodes[2] = 0; 
     this.counter = m; 
    } 

    public bool start() { 
     lock (_lock) { 
      if (this.nodes[0] != 0 && counter != 0) { 
       this.nodes[0]--; 
       this.nodes[1]++; 
       counter--; 
       return true; 
      } else 
       return false; 
    }} 

    public bool stop() { 
     lock (_lock) { 
      if (this.nodes[1] != 0) { 
       this.nodes[1]--; 
       this.nodes[2]++; 
       counter++; 
       return true; 
      } else 
       return false; 
    }} 
} 

мне нужно сделать start() метод ждать, пока counter не получим значение > 0. Я могу это сделать:

public bool start() { 
    while (this.counter == 0) { 
     Thread.Sleep(10); 
    } 

    lock (_lock) { 
     if (this.nodes[0] != 0 && counter != 0) { 
      this.nodes[0]--; 
      this.nodes[1]++; 
      counter--; 
      return true; 
     } else 
      return false; 
}} 

Но нет ли лучшего решения? Я имею в виду, похоже, что я могу потерять меньше времени, чтобы спать.

Чтобы посмотреть, для чего это необходимо. Я вызываю start перед началом потока и stop в конце потока. Таким образом, счетчик должен отражать максимальное количество потоков, выполняемых в одно и то же время.

+1

Ваш код вряд ли узнаваем как код C#. Взгляните на [Руководство по разработке рамок] (https://msdn.microsoft.com/en-US/library/ms229042 (v = vs.110) .aspx). Это похоже на книгу C++, – nvoigt

+1

Спасибо! Я буду читать это, поскольку я решаю все насущные проблемы. – InfernumDeus

+1

Вы также можете посмотреть 'BlockingCollection ' вместо массива для того, что вы хотите. –

ответ

1

Сигнализация, как это делается с использованием классов событий. В вашем случае должно быть достаточно ManualResetEventSlim.

Вы можете использовать Wait вместо цикла while, и вы можете Set его, когда счетчик достигает нуля.

1

Вы можете придумать использование «ManualResetEvent» для измельчения между двумя потоками.

Следующий непроверенный код может помочь.

class petriPool 
{ 
    private int[] nodes = new int[3]; 
    private int counter; 
    private ManualResetEvent mevent; 

    private readonly object _lock = new object(); 

    public petriPool (int n, int m) 
    { 
     mevent= new ManualResetEvent(false); 
     this.nodes[0] = n; 
     this.nodes[1] = 0; 
     this.nodes[2] = 0; 
     this.counter = m; 
    } 

    public bool start() 
    { 
     lock (_lock) 
     { 
      if (this.nodes[0] != 0 && counter != 0) 
      { 
       this.nodes[0]--; 
       this.nodes[1]++; 
       counter--; 

       if(counter>0) mevent.Set(); 

       return true; 
      } else 
       return false; 
     } 
    } 

    public bool stop() 
    { 
     mevent.WaitOne(); 

     lock (_lock) { 


      if (this.nodes[1] != 0) { 
       this.nodes[1]--; 
       this.nodes[2]++; 
       counter++; 
       return true; 
      } else 
       return false; 
     } 

     //reset 'mevent' if you want. 
    } 
} 
+1

Я добавил некоторое объяснение к вопросу. Я создаю объект с 5 n и 2 счетчиками. Все потоки запускались за один раз и, как все закончилось, программа просто перестала работать. Похоже, что-то не так. – InfernumDeus

Смежные вопросы