19

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.

Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
tomb
  • 1,817
  • 4
  • 21
  • 40

9 Answers9

56

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();
}
Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Florin Petriuc
  • 1,146
  • 9
  • 16
  • 2
    It's really unclear to me how this can fix the problem. Behaves exactly the same (but then again I can't reproduce the original problem either). – jeroenh Nov 16 '12 at 07:41
  • @jeroenh I completely agree. – tomb Nov 16 '12 at 07:43
  • @mrfishie can you still reproduce the original problem by reverting to Windows.Forms.Timer? – jeroenh Nov 16 '12 at 07:44
  • 21
    Windows.Forms.Timer doesn't work in console application or if it is used outside a form. – Florin Petriuc Nov 16 '12 at 07:46
  • 1
    @mrfishie are you doing any other work in your application that could be hogging the MainThread? Also try setting the System.Timer's `SynchronizingObject` to `this` and see if the problem shows up again. – Mark Hall Nov 16 '12 at 07:50
  • @MarkHall I am using PlayerIO, so that could be doing something. – tomb Nov 18 '12 at 06:39
  • @PetriucFlorin I am using it in a Windows form. – tomb Nov 18 '12 at 06:39
  • you are a god. thanks. this is nuts. I have other Forms timers working fine, but for one specific case, in the same application, I needed to change it to a system timer. – basher Oct 29 '18 at 21:20
10

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();
            }
        }
user3006708
  • 121
  • 1
  • 3
3

you may have started the timer from another thread, so try invoking it from the correct thread. for example, instead of:

timerX.start();

Use:

Invoke((MethodInvoker)delegate { timerX.Start(); });
MEHRDAD M
  • 31
  • 1
  • THANKS, I had same issue started timer from worker thread, everything looked fine, but tick event was not called. – Zoli Mar 08 '23 at 14:17
2

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
        {
            //
        }
    } 

}
Mark Hall
  • 53,938
  • 9
  • 94
  • 111
2

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.

Dmitry Ledentsov
  • 3,620
  • 18
  • 28
  • 1
    Really this is the best answer. Anytime I see explicit adding or removing of event handlers I look for a pre-baked RX solution or write an extension method to wrap the event handling with. Note that Take(3) not only does the three samples it also disposes of the event handler so you don't leak memory. All the above solutions forget to remove the event handler after getting the events. – bradgonesurfing Nov 17 '12 at 14:09
1

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

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

Paul Muia
  • 11
  • 3
0

I use the timer to update the status of a for loop. The timer won't fire no matter what I've done, but when I inserted 'Application.DoEvents()' in the loop it work fine.

MeSol
  • 1
  • 1
-1

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.

  • Welcome to SO! Please provide a code sample that implements your solution, as your current answer isn't very helpful. See also [How to answer questions](https://stackoverflow.com/help/how-to-answer). – hschne Nov 21 '20 at 12:18