How do I change the interval time in System.Threading.Timer from the callback function of this timer?

18,378

Solution 1

This line generate infinite recursion:

if(true)
    _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10));

The first parameter forces TimerCallBack to execute right away. So it executes it again and again indefinitely.

The fix would be

if(true)
    _timer.Change(TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));

Solution 2

The problem is that your call to Change specifies that the next call should happen immediately. If you're going to call Change every time, you can just use a period of Timeout.Infinite (which is just a constant of -1) to tell it to avoid repeating at all after the next time - but it will still keep firing, because that next time, you reset it. For example:

using System;
using System.Threading;

static class Program
{
    private static Timer timer = new Timer(TimerCallBack); 

    public static void Main()
    {
        timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
        Thread.Sleep(10000);

    }

    private static void TimerCallBack(object obj)
    {
        Console.WriteLine("{0}: Fired", DateTime.Now);
        timer.Change(TimeSpan.FromSeconds(3),
                     TimeSpan.FromMilliseconds(Timeout.Infinite));
    }
}

Alternatively, you could change it just once, and then leave it:

using System;
using System.Threading;

static class Program
{
    private static Timer timer = new Timer(TimerCallBack); 
    private static bool changed = false;

    public static void Main()
    {
        timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
        Thread.Sleep(10000);

    }

    private static void TimerCallBack(object obj)
    {
        Console.WriteLine("{0}: Fired", DateTime.Now);
        if (!changed)
        {
            changed = true;
            TimeSpan interval = TimeSpan.FromSeconds(3);
            timer.Change(interval, interval);
        }
    }
}

Note that nothing is using the initial interval (1 second in the samples above) in either case, because we're calling Change immediately - if you really want a different time before the first call, don't use TimeSpan.Zero in the initial call to Change.

Share:
18,378

Related videos on Youtube

mrbrooks
Author by

mrbrooks

Updated on June 04, 2022

Comments

  • mrbrooks
    mrbrooks almost 2 years

    How do I change the interval in System.Threading.Timer from the callback function of this timer? Is this correct?

    Doing so. Did not happen.

    public class TestTimer
    {
        private static Timer _timer = new Timer(TimerCallBack); 
    
        public void Run()
        {
            _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(1));
        }
    
        private static void TimerCallBack(object obj)
        {
            if(true)
                _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10));
        }
    
    }
    
    • crypted
      crypted almost 13 years
      @Mitch Wheat, that is valid for some good reason, testing for example ?
    • mrbrooks
      mrbrooks almost 13 years
      Mitch, it's just an example. Do not take it to heart. lol
    • Randall Deetz
      Randall Deetz almost 8 years
      plus 1 just because you need it
  • James Wilkins
    James Wilkins about 7 years
    Just for the record, while you can of course use -1 for "Infinite", the docs do say you can use Timeout.Infinite, which I think more clearly shows the intention. ;)
  • Jon Skeet
    Jon Skeet about 7 years
    @JamesWilkins: True Will edit. (Although if Timeout.Infinite were a TimeSpan it would be clearer - the docs for Timer.Change(int,int) mention Timeout.Infinite; the docs for Timer.Change(TimeSpan, TimeSpaan) don't :(
  • James Wilkins
    James Wilkins about 7 years
    Yeah, got to love the consistency there, lol. ;) Not surprised at all really, come to expect this, along with other useless doc info.
  • Sarrus
    Sarrus about 6 years
    For infinite value inTimer.Change(TimeSpan, TimeSpan) the Timeout.InfiniteTimeSpan field can be used.