Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Winforms Timer for Dummies

Tags:

winforms

timer

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.

like image 490
Mark Dickinson Avatar asked Jul 23 '09 21:07

Mark Dickinson


4 Answers

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.

like image 188
chakrit Avatar answered Nov 16 '22 01:11

chakrit


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.

like image 41
jasonh Avatar answered Nov 16 '22 00:11

jasonh


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.

like image 30
Henk Holterman Avatar answered Nov 16 '22 02:11

Henk Holterman


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;
    }
}
like image 27
Michael Petrotta Avatar answered Nov 16 '22 01:11

Michael Petrotta