没有响应的窗口在循环中形成控件

时间:2015-12-26 22:15:20

标签: c#

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

我通过定义vx&来尝试相同的代码。 vy作为属性get& set方法(例如set方法同时设置vxxVelV.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
                }
            }
        }
    }
}

2 个答案:

答案 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的许多答案的问题:

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