2015-12-26 3 views
0

При выполнении приведенного ниже кода метки в форме должны показывать значения vx и vy с помощью меток xVelV и yVelV. К сожалению, обе метки не реагируют во время цикла while. Однако, когда программа выходит из цикла, значения затем обновляются.Неотвеченные окна формируют элементы управления внутри цикла

Я попробовал один и тот же код, определив vx & vy как свойства с get & set методами (например, тем set метод установки значения vx и xVelV.text по совместительству), но до сих пор никаких изменений.

Может ли кто-нибудь выяснить, что я делаю неправильно?

примечание: есть g вне цикла в то время (как Graphics g = panel.CreateGraphics();), которая затем используется для рисования прямоугольников внутри блока в то время.

using System; 
using System.Drawing; 
using System.Windows.Forms; 

namespace fff { 
    class FormMain : Form {  
     // ... some code before 
     private Label xVelL = new Label(); 
     private Label yVelL = new Label(); 
     // ... some code after 

     public FormMain() { 
      // ... some code here 
      this.Controls.Add(xVelV); 
      this.Controls.Add(yVelV); 
      // ... some code here 
     } 

     public void RunG() {    
      // ... some code here 
      double x = 400.0, y = 050.0, xn, yn, vx, vy, ax, ay; 
      // ... some code here 
      bool massOut = false; 

      while (!massOut) { 
       // ... some code here 
       vx += ax; 
       vy += ay; 
       // ****** bug is here below !!! ****** 
       this.xVelV.Text = vx.ToString(); 
       this.yVelV.Text = vy.ToString(); 
       // ****** bug is here above !!! ****** 
       xn = x + vx; 
       yn = y + vy; 
       if (xn < 0 || xn > width || yn < 0 || yn > height) { 
        massOut = true; 
       } 
       else { 
        // ... some code here 
        x = xn; 
        y = yn; 
        // ... some code here 
       } 
      } 
     } 
    } 
} 
+1

Попробуйте добавить 'this.Refresh' после присвоения значения ваших TextBoxes. –

+2

Механизм формы не может ничего обновить до тех пор, пока вы не закончите обработку. Вы работаете в одном и том же потоке элементов управления формы, пока не закончите цикл. Вам необходимо использовать компонент [BackgroundWorker] (https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) и его событие ProgressChanged для обновления UI. – Steve

ответ

3

RunG() Выполняется в ответ на какое-то событие. Не уверен, что, но это должно быть. Это означает, что сообщение было снято с очереди сообщений в главном контуре сообщения программы, произошел фрейм-материал, обработчик события получил вызов, он называется RunG(), и основной цикл сообщения блокируется, пока все эти вещи не разматываются.

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

Элементы управления не могут перерисовываться до тех пор, пока основной цикл сообщения не станет бесплатным. Это не может сделать с одной нитью.

Чтобы обновить интерфейс, вам необходимо вызвать RunG() в другом потоке и Invoke() из него в поток пользовательского интерфейса. Только пользовательский интерфейс может касаться объектов пользовательского интерфейса, поэтому необходимо использовать функцию Invoke().

Вот вопрос, с большим количеством ответов об обновлении пользовательского интерфейса из из потока пользовательского интерфейса:

How to update the GUI from another thread in C#?

+0

В ответ на ваше первое предложение («RunG() выполняет в ответ на какое-то событие».): Да, он вызывается событием «KeyDown». Итак, ваш смысл имеет смысл. Я дам ему еще одну попытку с новым потоком. – ssd

+1

@ merkez3110 Легкая догадка - не много способов в приложении winforms для выполнения кода. Я добавил обновление о бизнесе Invoke. –

3

Это потому, что вы работаете функцию RunG из UI потока. Это означает, что весь другой код (обработка сообщений от других элементов управления) не может выполняться. Вы должны вызвать выполнение этого метода, или вы можете использовать такой код:

// this code is in method originally calling RunG(); 
Task.Run(() => { 
    RunG(); 
}); 

EDIT: Как правильно указано в комментарии, используя код выше, не достаточно. Вы также должны изменить методы, которые меняют элементы пользовательского интерфейса, например this.xVelV.Text = someValue;. Вы должны Invoke этот метод:

this.xVelV.Invoke((Action)delegate() { this.xVelV.Text = someValue; }); 

Вызывая, выполняется код выполняется в контексте UI потоке этого TextBox. Без Invoke любой код, запущенный в другом потоке (отличном от потока пользовательского интерфейса, создавшего элемент пользовательского интерфейса), вызовет исключение.

+0

. Вы не можете просто сказать запустите 'RunG' в фоновом потоке, поскольку' RunG' обновляет компоненты пользовательского интерфейса. Чтобы это было хорошим ответом, вам нужно решить эту проблему. – Enigmativity

+0

@ Enigmativity Большое спасибо, я совсем забыл упомянуть об Invoking. Я редактировал свой пост, надеюсь, все будет в порядке. –

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