【问题标题】:label text not displaying correct value but messagebox.show does标签文本未显示正确的值,但 messagebox.show 显示
【发布时间】:2012-04-30 10:31:22
【问题描述】:

我在 C#.NET 中有一个似乎不是“更新”的简单标签。它仅显示我的应用程序的第一个初始值。在下面的代码中,“score”变量不会更新,但是在调用 messagebox.show 对话框时它会显示正确的值。分数值在不同的线程中更改,但我不认为这是调用和跨线程表单控制的问题(因为我在创建 label6 的线程中调用此代码)。

有谁知道可能是什么解决方案?我尝试了 Application.DoEvents() 方法但无济于事。此外,label6.Update() 和 label6.Refresh() 在 label6.Text = score 行之后似乎都不起作用。

Player 是我创建的一个类,将分数值保存为公共 int。

    public Form1()
    {
        InitializeComponent();
        createGame();
    }
    public void createGame()
    {
        InitializeComponent();
        drawThread = new Thread(draw);  
        MessageBox.Show(player.score);
        label6.Text = player.score;
    }
    public void draw()
    {
        //do drawing, change player.score value
        //end thread
    }
    public void button_click()
    {
        if(firstrun)
            drawThread.Start()
        else{
            createGame()
            drawThread.Start()
        }

    }

编辑(来自 cmets): 这是一个 WinForms 应用程序。 label6.Text = score 行是调用 label6 的唯一实例,而不是在 Visual Studio 生成的 Form.Designer 代码中实例化。

【问题讨论】:

  • 好的,你的主线程在做什么,那么,什么时候应该处理重绘等消息?
  • 一个 - 通常你永远不想从你的代码中调用Application.DoEvents。其次,你确定这家伙背后没有其他代码将标签文本设置为其他内容吗?
  • 可能你的标签没有更新,因为主线程很忙,无法处理消息队列。你能告诉我们更多代码吗?
  • +1 for @Tejs 拒绝浪费 CPU 的递归生成器。
  • 我认为代码将有助于检查您在 MessageBox 和 Label 中从何处获得价值...

标签: c# .net winforms string


【解决方案1】:

只需在标签上执行Refresh()

label6.Refresh();

【讨论】:

  • 如果Application.DoEvents()不处理队列,为什么label.Refresh()应该解决问题?
  • 设置Text属性时这不是自动完成的吗?
  • @MartinJames:不,当您更新 Text 属性时,画布可能已失效...但是在主线程处理消息队列并执行重绘之前,控件仍保留旧值...
  • @Marco - 是的,我知道必须先处理生成的 Windows 消息,然后才能将这些更改的属性实际呈现到显示器上。
【解决方案2】:

在你的代码中我看到了

drawThread = new Thread(draw);

但是在单击按钮时,您会调用draw.Start(),所以我认为您的渲染线程根本没有启动!你不应该使用drawThread.Start()吗?
更多:您不能从不同于主线程的线程访问图形控件属性,您应该使用Invoke...

我在这里看到一个问题:

  1. drawThread = new Thread(draw);
    MessageBox.Show(player.score);

    有了这些行,第二个线程被启动并立即显示 MessageBox(第二个线程可能尚未终止)

  2. label6.Text = player.score;
    当您关闭 MessageBox 时,将执行此行:如果第二个线程终止并且已经更新了分数,您将获得预期的结果;如果第二个线程仍在执行,则在您的标签中您仍然可以找到以前的分数。

因此,如果不知道您的第二个线程是做什么的,我无法知道您的代码是否正确。
在我看来,当它终止时,你应该从你的第二个线程(使用Invoke)更新label6.Text;如果没有,你为什么要使用第二个线程?
通常我们使用线程来执行长时间执行而不阻塞主线程(负责更新表单和处理用户输入),因此您应该在需要时更新这些线程的属性。
考虑使用BackgroundWorker

【讨论】:

  • 绘图线程未访问图形控件。 drawThread 更新单独类中的值(分数)。 label.text 在创建它的主线程中重新绘制。
  • 我已经修复了您在我的原始帖子中描述的内容。 draw.Start() 是我复制代码时的拼写错误。其实就是drawThread.Start()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
相关资源
最近更新 更多