C# while循环中的无响应windows窗体控件

C# while循环中的无响应windows窗体控件,c#,C#,运行下面的代码时,表单中的标签应通过标签xVelV和yVelV显示vx和vy的值。不幸的是,这两个标签在while循环期间都没有响应。但是,当程序退出循环时,值会随之更新 我用get&set方法(比如set方法同时设置vx和xVelV.text的值)将vx和vy定义为属性,尝试了相同的代码,但仍然没有改变 有人知道我做错了什么吗 注意:在while循环外定义了一个g(如Graphics g=panel.CreateGraphics();),然后用于在while块内绘制矩形 using Syste

运行下面的代码时,表单中的标签应通过标签
xVelV
yVelV
显示
vx
vy
的值。不幸的是,这两个标签在
while
循环期间都没有响应。但是,当程序退出循环时,值会随之更新

我用
get
&
set
方法(比如
set
方法同时设置
vx
xVelV.text
的值)将
vx
vy
定义为属性,尝试了相同的代码,但仍然没有改变

有人知道我做错了什么吗

注意:在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
                }
            }
        }
    }
}
使用系统;
使用系统图;
使用System.Windows.Forms;
名称空间fff{
类FormMain:Form{
//…以前有一些代码
私有标签xVelL=新标签();
私有标签yVelL=新标签();
//…后面有一些代码
public FormMain(){
//…这里有一些代码
this.Controls.Add(xVelV);
this.Controls.Add(yVelV);
//…这里有一些代码
}
public void RunG(){
//…这里有一些代码
双x=400.0,y=050.0,xn,yn,vx,vy,ax,ay;
//…这里有一些代码
bool-massOut=false;
而(!massOut){
//…这里有一些代码
vx+=ax;
vy+=ay;
//******下面是bug******
this.xVelV.Text=vx.ToString();
this.yVelV.Text=vy.ToString();
//******上面有bug******
xn=x+vx;
yn=y+vy;
如果(xn<0 | | xn>宽度| | yn<0 | | yn>高度){
massOut=true;
}
否则{
//…这里有一些代码
x=xn;
y=yn;
//…这里有一些代码
}
}
}
}
}

这是因为您正在从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; });

通过调用,执行的代码在该文本框的UI线程上下文中运行。不调用在其他线程中运行的任何代码(与创建UI元素的UI线程不同)将导致异常。

这是因为您正在从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; });
通过调用,执行的代码在该文本框的UI线程上下文中运行。如果不调用在其他线程中运行的任何代码(与创建UI元素的UI线程不同),将导致异常。

RunG()正在执行以响应某种事件。不知道是什么,但一定是。这意味着一条消息被从程序的主消息循环中的消息队列中拉出,框架的东西发生了,一个事件处理程序被调用,它被称为RunG(),主消息循环被阻塞,直到所有的东西都被释放

之后,消息循环可以开始处理这些控件的绘制消息,UI线程可以自由地执行控件更新工作

在主消息循环空闲之前,控件无法重新绘制自己。这不能用一个线程来完成

您需要在另一个线程中调用RunG(),并定期将其调用到UI线程中以更新UI。只有UI线程可以接触UI对象,因此Invoke()是必需的

以下是一个关于从UI线程外更新UI的问题,有很多答案:

正在执行RunG()以响应某种事件。不知道是什么,但一定是。这意味着一条消息被从程序的主消息循环中的消息队列中拉出,框架的东西发生了,一个事件处理程序被调用,它被称为RunG(),主消息循环被阻塞,直到所有的东西都被释放

之后,消息循环可以开始处理这些控件的绘制消息,UI线程可以自由地执行控件更新工作

在主消息循环空闲之前,控件无法重新绘制自己。这不能用一个线程来完成

您需要在另一个线程中调用RunG(),并定期将其调用到UI线程中以更新UI。只有UI线程可以接触UI对象,因此Invoke()是必需的

以下是一个关于从UI线程外更新UI的问题,有很多答案:


尝试添加
此。将值分配给文本框后刷新
。表单引擎在您结束处理之前无法更新任何内容。您正在表单控件的同一线程上运行,因此在结束循环之前不会刷新。您需要使用组件及其ProgressChanged事件来更新UITry,添加
this。将值分配给文本框后刷新
。在您结束处理之前,表单引擎无法更新任何内容。你在跑步