Mars
Mars

Reputation: 930

Canceling Timer after x intervals

I have a timer that's supposed to run x times in 500ms intervals. Currently my code looks something like this:

 var i = 0;
 var times = 10;
 timer = new System.Threading.Timer(_ =>
 {
    if (timer == null || i >= times)
        return;

    Console.WriteLine("Run " + i);

    if (i < times - 1)
        i++;
    else
    {
        timer.Dispose();
        timer = null;
    }
 }, null, 500, 500);

Is this a reliable way to cancel the timer, if I make sure only one gets created and referenced in the timer variable?

The amount of intervals is variable at run-time.

Upvotes: 0

Views: 348

Answers (2)

Richard Schneider
Richard Schneider

Reputation: 35464

Looks pretty safe for the disposing of timer. I would make the i and times variables private and not part of the method. This creates faster code. Also, there is a slight possibility that the timer delegate could be running simultaneously on different threads, see http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx, so I might use the Interlocked.Increment method.

Maybe something like this:

class Foo
{
  volatile int runCount;
  int maxRunCount;
  Timer timer;

  void RunFor(int max)
  {
    maxRunCount = max;
    timer = new System.Threading.Timer(_ =>
    {
      if (timer == null) return;
      Console.WriteLine("Run " + runCount);

      if (Interlocked.Increment(ref runCount) == maxRunCount)
      {
          timer.Dispose();
          timer = null;
      }
    }, null, 500, 500);
  }
}

[EDIT]

On review of the code, I might throw a lock around the dispose of timer, to prevent race conditions.

    if (...)
    {
       lock(this)
       {
          if (timer != null) timer.Dispose();
          timer = null;
       }
     }

Upvotes: 2

Blachshma
Blachshma

Reputation: 17405

You should use the System.Timers.Timer class instead...
It supports both Stop() and Start() methods.

Short example:

System.Timers.Timer timer = new System.Timers.Timer();
var i = 0;
var times = 10;


public SetupTimer()
{
    timer.Interval = 500;
    timer.Elapsed += OnTimerElapsed;
    timer.Start();
}

private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // Logic

    if (i > times)
    {
       timer.Stop();
    }
}

Upvotes: 1

Related Questions