TextBox未更新

时间:2015-03-29 01:41:49

标签: c# winforms timer

我的Windows窗体上有一个textBox2(确认名称和拼写)我将一个计时器从工具箱中吸取到我的窗体上,它被命名为timer1。我试图让按钮按下时启动计时器,并让textBox2显示每个递增秒,以便显示整个过程花费了多长时间的运行时间。我在哪里错了?

public partial class Form1 : Form
{
    private int duration = 0;
    private void button1_Click(object sender, EventArgs e)
    {
        timer1.Enabled = true;
        timer1.Start();
        First();
        Second();
        Thirds();
        Fourth();
        Fifth();
        timer1.Stop();
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        duration++;
        textBox2.Text = duration.ToString();
    }
}

1 个答案:

答案 0 :(得分:2)

目前尚不清楚方法First()Second()等代表什么。但基于其余的代码,似乎这些是你想要计时的长期任务。

在任何情况下,问题是在您停止计时器之前,您永远不会从button1_Click()方法返回。计时器滴答在UI线程中引发,并且只有在UI线程未被处理其他事件阻止时才能引发。就像处理button1的{​​{1}}事件一样。

您应该在单独的线程中执行长时间运行的操作,例如使用Click。然后计时器将正常工作,或者您甚至可以使用Task方法中的循环来显示已用时间,无论您喜欢哪个。

例如:

async

注意:

  • 上面的示例中使用了private int duration = 0; private async void button1_Click(object sender, EventArgs e) { timer1.Enabled = true; timer1.Start(); await Task.Run(() => { First(); Second(); Thirds(); Fourth(); Fifth(); }); timer1.Stop(); } private void timer1_Tick(object sender, EventArgs e) { duration++; textBox2.Text = duration.ToString(); } 功能,C#5.0的新功能。请参阅下文,了解与旧版本的C#和.NET兼容的不同方法。
  • 使用await时,包含语句的await方法将执行“等待”表达式。此时,线程的控制权将返回给async方法的调用者。稍后,当等待的表达式最终完成时,线程的控制将在之前产生的点(即async语句)返回到async方法。
  • 在上文中,这意味着包含在await中的五个方法在另一个线程中异步执行。当Task启动时,Task方法实际返回其调用者。如果他们(即button1_Click())最终完成,Task方法的执行将在下一个语句中继续执行:button1_Click()


timer1.Stop() / async功能使得使用异步操作的代码更容易编写。但即使在此之前,还有其他机制可以做同样的事情。这是一种使用await对象的机制:

BackgroundWorker

注意:

  • 创建private async void button1_Click(object sender, EventArgs e) { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (sender1, e1) => { First(); Second(); Thirds(); Fourth(); Fifth(); }; worker.RunWorkerCompleted += (sender1, e1) => { timer1.Stop(); }; timer1.Enabled = true; timer1.Start(); worker.RunWorkerAsync(); } 对象时,它会捕获当前的同步上下文(如果有),稍后将用于引发除BackgroundWorker之外的所有BackgroundWorker个事件。
  • 使用线程池线程(即主UI线程以外的某个线程)引发DoWork事件。即使在执行长时间运行的工作时,这也允许在UI线程上发生事情。
  • 上面的代码可能看起来有些颠倒。这是因为稍后执行的部分实际上是作为订阅DoWorkDoWork事件的匿名方法声明的。
  • 声明了这些匿名方法并将它们订阅了它们的事件后,代码实际上启动了计时器,然后是RunWorkerCompleted本身。只有在调用BackgroundWorker方法时,工作人员才会通过提升RunWorkerAsync()事件来开始运行。


顺便说一句,虽然我保留原始代码尽可能完整,但请注意您不需要 DoWorktimer1.Enabled = true;。要么足以启动计时器;你可以使用你喜欢的任何一个,而忽略另一个。