运行以下代码时,表单中的标签应通过标签vx
和vy
显示xVelV
和yVelV
的值。不幸的是,在while
循环期间,两个标签都没有响应。但是,当程序退出循环时,值会更新。
我通过定义vx
&来尝试相同的代码。 vy
作为属性get
& set
方法(例如set
方法同时设置vx
和xVelV.text
的值),但仍然没有变化。
有人能弄清楚我做错了吗?
注意:在while循环之外定义g
(如Graphics g = panel.CreateGraphics();
),然后用于在while块内绘制矩形。
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
}
}
}
}
}
答案 0 :(得分:3)
这是因为您正在从UI线程运行函数RunG
。这意味着所有其他代码(处理来自其他控件的消息)无法运行。
您必须调用执行该方法,或者您可以使用以下代码:
// this code is in method originally calling RunG();
Task.Run(() => {
RunG();
});
编辑:正如评论中正确指出的那样,使用上面的代码是不够的。您还必须更改正在更改UI元素的方法,例如this.xVelV.Text = someValue;
。您必须调用该方法:
this.xVelV.Invoke((Action)delegate() { this.xVelV.Text = someValue; });
通过调用,执行的代码在该TextBox的UI线程的上下文中运行。没有调用任何在其他线程中运行的代码(与创建UI元素的UI线程不同)将导致异常。
答案 1 :(得分:3)
RunG()正在执行以响应某种事件。不确定是什么,但一定是。这意味着消息被从程序的主消息循环中的消息队列中拉出,框架内容发生了,调用了一个事件处理程序,它调用了RunG(),并且主消息循环阻塞,直到所有这些东西都展开。
之后,消息循环可以开始处理这些控件的绘制消息,UI线程可以自由地进行控制更新工作。
在主消息循环空闲之前,控件不能重绘自己。 不能使用单个线程完成。
您需要在另一个线程中调用RunG(),并从那里调用Invoke()定期进入UI线程以更新UI。只有UI线程可以触摸UI对象,因此Invoke()是必要的。
这是一个关于从UI线程中更新UI的许多答案的问题: