2015-07-21 3 views
0

Итак, я получил глобальные переменные, которые были изменены с помощью события SerialPort.DataReceived. Они обновляются каждые 100 мс. Теперь в другом методе у меня есть цикл while, делающий материал, соответствующий этим переменным. Но пока внутри этого цикла не будут замечены изменения переменных. Я отлаживал переменные и печатал их в своей форме; они меняются во время цикла while, но сам цикл не получает его.Обновить глобальную переменную во время цикла

struct position 
    { 
     public ushort value; 
     public int overflow; 
     public int steps; 
    } 

position actual, 
     target; 
int Error; 



private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     if (ProtIn.read(serialPort1)) 
     { 
      switch (ProtIn.command) 
      { 
       case "80": 
        actual.value = ProtIn.data; 
        break; 

       case "69": 
        Error = ProtIn.data; 
        break; 
      } 
      Invoke(new MethodInvoker(update_ui)); 
      } 
    } 



private void button1_Click(object sender, EventArgs e) 
    { 
     int steps = 45000; 
     drive_lock = false; 
     do 
     { 
      if (steps > 32760) 
      { 
       drive_lock = true; 
       if (steps > 0) 
       { 
        target.value = (ushort)(actual.value + 32760); 
        steps -= 32760; 
       } 
       else 
       { 
        target.value = (ushort)(actual.value - 32760); 
        steps += 32760; 
       } 
      } 
      else 
      { 
       drive_lock = false; 
       target.value = (ushort)(actual.value + steps); 
      } 

      ProtOut.build('G', target.value.ToString()); 
      ProtOut.send(serialPort1); 

      if (drive_lock) 
       while ((Error & 0xE0) >> 5 != 0) 
       { 
        Thread.Sleep(200); 
       } 
     } while (drive_lock); 
    } 

private void update_ui() 
    { 
     richTextBox1.AppendText(System.Text.Encoding.Default.GetString(ProtIn.in_buff) + Environment.NewLine); 

     tBox_actual.Text = actual.value.ToString(); 
     txtBox_overflow_actual.Text = actual.overflow.ToString(); 

     if ((Error & 0xE0) >> 5 != 0) 
      lbl_motion.Text = "Moving"; 
     else 
      lbl_motion.Text = "Standing"; 

    } 
+1

Вы не изображены код? –

+0

Добавлен код. Надеюсь, вы сможете это получить. Это некоторая работа в процессе и становится все больше и больше ... – Patrick

+0

Какой поток выполняет обратный вызов последовательного порта ('serialPort1_DataReceived')? Может быть, вы блокируете поток пользовательского интерфейса с помощью вашего цикла, чтобы сообщения данных последовательного порта никогда не доходили до вашего приложения? – JimmyB

ответ

0

я предлагаю что-то вдоль этих линий:

struct position 
    { 
     public ushort value; 
     public int overflow; 
     public int steps; 
    } 

position actual, 
     target; 
int Error; 

int steps; 

private bool isMoving() { 
    return ((Error & 0xE0) >> 5 != 0); 
} 

private void moveIt() { 

    if (steps == 0) { 
     return; // Nothing to do. 
    } 

    if (isMoving()) { 
     // Still moving, do nothing. 
     return; 
    } 

    if (steps > 32760) 
    { 
     drive_lock = true; 
     if (steps > 0) 
     { 
      target.value = (ushort)(actual.value + 32760); 
      steps -= 32760; 
     } 
     else 
     { 
      target.value = (ushort)(actual.value - 32760); 
      steps += 32760; 
     } 
    } 
    else 
    { 
     drive_lock = false; 
     target.value = (ushort)(actual.value + steps); 
    } 

    ProtOut.build('G', target.value.ToString()); 
    ProtOut.send(serialPort1); 

} 

private void button1_Click(object sender, EventArgs e) { 
     steps = 45000; 
     drive_lock = false; 
     moveIt(); 
} 

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (ProtIn.read(serialPort1)) 
    { 
     switch (ProtIn.command) 
     { 
      case "80": 
       actual.value = ProtIn.data; 
       break; 

      case "69": 
       Error = ProtIn.data; 

       moveIt(); // <<====    

       break; 
     } 

     Invoke(new MethodInvoker(update_ui)); 

     } 
} 



private void update_ui() 
    { 
     richTextBox1.AppendText(System.Text.Encoding.Default.GetString(ProtIn.in_buff) + Environment.NewLine); 

     tBox_actual.Text = actual.value.ToString(); 
     txtBox_overflow_actual.Text = actual.overflow.ToString(); 

     if ((Error & 0xE0) >> 5 != 0) 
      lbl_motion.Text = "Moving"; 
     else 
      lbl_motion.Text = "Standing"; 

    } 

(. Дайте или занять некоторую синхронизацию в случае фактически являются несколько потоками, участвующими)

Обратите внимание, что мы называем moveIt() всякий раз, когда нам нужны управляемый выход. Это тот случай, когда мы сначала запускаем процедуру (через кнопку 1), а затем только когда значение Error действительно изменяется, которое мы обнаруживаем синхронно сразу после того, как данные были получены из порта.

+0

Как я уже говорил, я не могу называть 'moveIt()' на каждом событии 'serialPort1_DataReceived'. Сейчас я пробую дыру другим способом. Без события 'serialPort1_DataReceived' и с ручным вызовом' ProtIn.read (serialPort1) '. – Patrick

+0

«Я не могу вызвать moveIt() для каждого события serialPort1_DataReceived» - И я не понимаю, почему вы не должны этого делать. Для меня это похоже на то, что мой код делает именно то, что делает ваш, просто без (случайной) задержки 0 ~ 200 мс для следующей команды перемещения. – JimmyB

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