Reputation: 930
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
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
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