Winforms Timer for Dummies

2019-01-11 11:17发布

I'm trying to get a timer to tick once a second in a winform, when I look for advice on how to do this I find loads of stuff about threads. Well I don't care about threads, because all I'm trying to do is make a value count down from 60 to 0 in one minute, then stop. I don't think we need to go into cloud computing to solve this one, but I am really a web forms bod, so I'm a bit rusty on this issue. Can anyone point me to an example

Here's what I tried

private void button1_Click(object sender, EventArgs e)
    {
        this.timeLeft = 60;
        this.label1.Visible = false;
        this.button1.Visible = false;
        gt = new Timer();
        gt.Tick += new EventHandler(CountDown);
        gt.Interval = 1000;
        gt.Start();
    }

private void CountDown(object sender, EventArgs e)
{
    do
    {
        this.TimeBar.Value = timeLeft;                
        this.timeLeft -= 1;
    } while (this.timeLeft > 0);
    if (this.TimeBar.Value > 0) return;
    gt.Stop();
    this.label1.Visible = true;
    this.button1.Visible = true;
}

Any help would be appreciated.

4条回答
成全新的幸福
2楼-- · 2019-01-11 11:23

What's happening is that you're decrementing the timeLeft variable until it reaches zero on the very first tick of the timer. Take out the do...while loop and you'd have a basically working example.

However if you're going to be doing any amount of Windows Forms work, you need to learn about threading and how that affects the UI. You'll very quickly find yourself back here if you don't with tales of unhelpful exceptions and misbehaving UI components. Jon Skeet has an excellent threading series. I highly recommend it. It has a section devoted to timers, so that might give you some additional insight.

查看更多
等我变得足够好
3楼-- · 2019-01-11 11:33

You don't need threading if you use the winforms' timer.

Drop a Timer control on your page, name it "timer" and paste the following code:

public MainForm()
{
    InitializeComponent();

    timer.Interval = 1000;
    timer.Start();

    timeLeft = 60;
    timer.Tick += Timer_Tick;

    // start things
    label1.Hide();
    button1.Hide();
    timer.Start();

}

public void Timer_Tick(object sender, EventArgs e)
{
    timeLeft--;

    if (timeLeft <= 0) {
        timer.Stop();
        label1.Show();
        button1.Show();
    }
}

I suppose if you've come from a webby background, Events-driven programming is probably the thing you need to get start reading about if you want to understand how stuff on the desktops are programmed.

查看更多
我只想做你的唯一
4楼-- · 2019-01-11 11:36

Apart from taking out the loop (as per jasonh's answer), your approach could become a little inaccurate if the app is kind of busy. Although you specify their interval in milliseconds, WinForms timers have a 18 ms resolution and have a very low priority, the message loop only checks timers if it finds nothing else to do.

So, keep a StartTime (DateTime) value and use that to calculate the remaining time in every Timer event. You just could need 61 tick to reach a minute.

查看更多
对你真心纯属浪费
5楼-- · 2019-01-11 11:39

You don't want to do any looping in your event handler. The handler is called once per timer 'tick' - every 1000 milliseconds, as you've configured it. So you want to decrement your timeLeft variable once per call, then shut the whole thing down when timeLeft hits zero.

// untested
private void CountDown(object sender, EventArgs e)
{
    this.TimeBar.Value = timeLeft;
    this.timeLeft--;
    if (this.TimeBar.Value == 0)
    {
        gt.Stop();
        this.label1.Visible = true;
        this.button1.Visible = true;
    }
}
查看更多
登录 后发表回答