2016-03-07 2 views
1

Я довольно новичок в потоковом в общем, и я хочу попробовать его на C#. Я пытаюсь сделать базовое моделирование тоннажа чего-то, которое разлагается каждые 20 секунд и заправляется каждые 10 секунд. Из того, что я читал, безопасность потоков - это то, что мне нужно учитывать, поскольку есть два потока; один для разложения переменной тоннажа на 160, один для добавления случайной суммы в тоннаж, и поскольку они совершают транзакции с переменной тоннажем, я должен убедиться, что к ним обращаются правильно.Как использовать блокировки потоков в бесконечном цикле?

Я прочитал о том, как использовать lock (object), и я понимаю концепцию для простых примеров потоков, но как я могу использовать его для двух потоков, работающих навсегда, и должен своевременно корректировать тоннаж?

Вот что у меня есть, но когда я блокирую весь цикл, другая нить никогда не появляется. Или у меня неправильная структура кода?

public double tonnage = 1000; 
private object x = new object(); 

//Starts the simulation, runs forever until user ends the simulation 
private void btnStart_Click(object sender, EventArgs e) 
{ 
    //Decay Tonnage 
    Thread decayTonnageThread = new Thread(() => decayTonnage (tonnage)); 
    decayTonnageThread .Start(); 

    //Add Tonnage 
    Thread addTonnageThread = new Thread(() => addTonnage (tonnage)); 
    addTonnageThread .Start(); 
} 

//I want to decay the tonnage every 20 seconds 
public void decayTonnage (double tonnage) 
    { 
     lock(x) 
     { 
      while (true) 
      { 
       tonnage = tonnage - 160; 
       Thread.Sleep(20000); 
      } 
     } 
    } 

//Add to the tonnage every 10 seconds 
public void addTonnage (double tonnage) 
    { 
     lock(x) 
     { 
      while (true) 
      { 
       Random random = new Random(); 
       double randomNumber = random.Next(97, 102); 
       tonnage = tonnage + randomNumber; 
       Thread.Sleep(10000); 
      } 
     } 
    } 
+5

Вы хотите сделать свою блокировку внутри петель, а не снаружи. – adv12

+1

Используйте блокировку только при изменении тоннажа, исключая остальную часть кода. Возможно, с помощью [Interlocked class] (https://msdn.microsoft.com/nl-nl/library/system.threading.interlocked (v = vs.110) .aspx) может быть хорошей идеей –

+0

@ adv12 это сработало спасибо ! –

ответ

5

Вы хотите, чтобы замок, чтобы быть как можно меньше, только вокруг линий, взаимодействующих с разделяемыми объектами, а не весь цикл. Кроме того, помещая Random random = new Random(); в цикл while is a bad habit to have, вы должны сделать только один случайный экземпляр и инициализировать его вне цикла.

//I want to decay the tonnage every 20 seconds 
public void decayTonnage (double tonnage) 
{ 

     while (true) 
     { 
      lock(x) 
      { 
       tonnage = tonnage - 160; 
      } 
      Thread.Sleep(20000); 
     } 
} 

//Add to the tonnage every 10 seconds 
public void addTonnage (double tonnage) 
{ 

     Random random = new Random(); 
     while (true) 
     { 
      double randomNumber = random.Next(97, 102); 
      lock(x) 
      { 
       tonnage = tonnage + randomNumber; 
      } 
      Thread.Sleep(10000); 
     } 
} 

Кроме того, я предполагаю, что вы делаете это для какой-то уступки и должны использовать потоки, но если бы я делал это по-настоящему, я бы не использовать потоки с петлями + а Sleep на всех, и вместо того, чтобы использовать два таймера , который стрелял каждые 20 секунд и один, который срабатывал каждые 10 секунд. В зависимости от type of timer you use вы можете или не можете использовать блокировку.

+0

Я попробую это, и да, я вижу, что имеет смысл блокировать только линии, взаимодействующие с общими объектами. Это не для задания, его для работы (еще не в производстве). Я пытаюсь смоделировать моделирование того, что произойдет, если пользователь изменит несколько переменных, поэтому я пошел с потоками. Благодарю вас за то, что я использую таймеры. –

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