18
votes

I have a Windows.Forms.Timer in my code, that I am executing 3 times. However, the timer isn't calling the tick function at all.

private int count = 3;
private timer;
void Loopy(int times)
{
    count = times;
    timer = new Timer();
    timer.Interval = 1000;
    timer.Tick += new EventHandler(timer_Tick);
    timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
    count--;
    if (count == 0) timer.Stop();
    else
    {
        // Do something here
    }
}

Loopy() is being called from other places in the code.

7
From where you are calling Loopy? - Adil
Loopy() is being called from another place in the code. - tomb
Well calling it from other places overwrites the current timer object. There's your problem. - Cole Tobin
How are you verifying that the timer isn't ticking? Where are you calling the Loopy function? Best to provide a minimal but complete sample demonstrating the problem. Very likely you will solve it yourself then. - jeroenh
This code is fine and works. Problem is elsewhere in code that you are not showing. - jeroenh

7 Answers

51
votes

Try using System.Timers instead of Windows.Forms.Timer

void Loopy(int times)
{
    count = times;
    timer = new Timer(1000);
    timer.Enabled = true;
    timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
    timer.Start();
}

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    throw new NotImplementedException();
}
8
votes

If the method Loopy() is called in a thread that is not the main UI thread, then the timer won't tick. If you want to call this method from anywhere in the code then you need to check the InvokeRequired property. So your code should look like (assuming that the code is in a form):

        private void Loopy(int times)
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate
                {
                    Loopy(times);
                });
            }
            else
            {
                count = times;
                timer = new Timer();
                timer.Interval = 1000;
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }
        }
2
votes

I am not sure what you are doing wrong it looks correct, This code works: See how it compares to yours.

public partial class Form1 : Form
{
    private int count = 3;
    private Timer  timer;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Loopy(count);
    }

    void Loopy(int times)
    {
        count = times;
        timer = new Timer();
        timer.Interval = 1000;
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        count--;
        if (count == 0) timer.Stop();
        else
        {
            //
        }
    } 

}
2
votes

Here's an Rx ticker that works:

Observable.Interval(TimeSpan.FromSeconds(1))
.Take(3)
.Subscribe(x=>Console.WriteLine("tick"));

Of course, you can subscribe something more useful in your program.

1
votes

If you are using Windows.Forms.Timer then should use something like following.

//Declare Timer
private Timer _timer= new Timer();

void Loopy(int _time)
{

    _timer.Interval = _time;
    _timer.Enabled = true;
    _timer.Tick += new EventHandler(timer_Elapsed);
    _timer.Start();
}

void timer_Elapsed(object sender, EventArgs e)
{
    //Do your stuffs here
}
1
votes

Check if your timer in properties is enabled. Mine was false and after setting to true it worked.

0
votes

If you use some delays smaller than the interval inside the timer, the system.timer will execute other thread and you have to deal with a double thread running at the same time. Apply an InvokeRequired to control the flow.