如何在事件后更新按钮文本

时间:2012-09-26 21:53:14

标签: c# refresh

我正试图让一个程序发布一堆文本。用户输入文本,消息量以及必须传递的速度。程序繁忙时,按钮文本需要“停止”而不是“开始”。在您最初启动它之后按下按钮强制它停止时,文本将更改回“开始”,但是在传送给定数量的消息后程序停止时不会发生这种情况,即使代码已到位且不会产生错误。

我有一种感觉,这是因为文字由于某种原因没有更新。我试图用Invalidate()和Update()来刷新它,但这不起作用。如何解决这个问题?

以下是代码:

private void button1_Click(object sender, EventArgs e)
    {
        if (button1.Text == "Start")
        {
            isEvil = true;
            button1.Text = "Stop";

            Thread t = new Thread(StartTyping);
            t.Start(textBox1.Text);
        }
        else
        {
            isEvil = false;
            button1.Text = "Start";
        }
    }

    private void StartTyping(object obj)
    {
        string message = obj.ToString();
        int amount = (int)numericUpDown2.Value;
        Thread.Sleep(3000);


        for (int i = 0; i < amount; i++)
        {
            if (isEvil == false)
            {
                //////This does NOT work
                //button1.Text = "Start";
                //button1.Invalidate();
                //button1.Update();
                //button1.Refresh();
                //Application.DoEvents();
                break;
            }

            SendKeys.SendWait(message + "{ENTER}");
            int j = (int)numericUpDown1.Value * 10;
            Thread.Sleep(j);
        }
    }

5 个答案:

答案 0 :(得分:2)

您有四个答案告诉您从UI线程更新UI内容,但没有一个解决您的代码中的逻辑流问题。

之所以没有发生这种情况,是因为当isEvilfalse时,它只会在for-loop 中发生isEvil何时设置为false?只有当你点击“停止”,而不是其他地方。

如果您希望按钮在线程完成后返回“开始”,而不单击“停止”,则需要在循环之后添加代码来执行此操作,与值无关isEvil :(撇开VoidMain的回答)

private void StartTyping(object obj)
{
    string message = obj.ToString();
    int amount = (int)numericUpDown2.Value;
    Thread.Sleep(3000);

    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            if (button1.InvokeRequired)
            {
                button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
            }
            else
            {
                button1.Text = "Start";
            }
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }

    if (button1.InvokeRequired)
    {
        button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
    }
    else
    {
        button1.Text = "Start";
    }
}

现在您有重复的代码,因此您可能希望将其拆分为单独的方法。

答案 1 :(得分:0)

您需要在UI线程上更新UI。

尝试一下名为 SynchronizationContext 的内容。 google时有很多例子。

如果您在 WPF Silverlight 中,则可以使用调度程序。同样,如果您在Google或StackOverflow中搜索这些关键字,还有很多示例。

答案 2 :(得分:0)

您必须从UI线程更新控件。这就是你如何为winforms做的。

    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            button1.Invoke(new Action(() => button1.Text = "Start"));
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }

这将阻止button1获取其文本更新。如果您不希望阻止,请将Invoke替换为BeginInvoke

答案 3 :(得分:0)

这样的事情(未经测试)应该工作:

private void StartTyping(object obj)
{
    string message = obj.ToString();
    int amount = (int)numericUpDown2.Value;
    Thread.Sleep(3000);


    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            if(button1.InvokeRequired)
            {
                button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
            }
            else
            {
                button1.Text = "Start";
            }
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }
}

答案 4 :(得分:0)

最好的办法是使用BackgroundWorker。在这里添加一个简洁的例子有点太过于操作但有一个decent tutorial from O'Reilly