I am trying to delay events in my method by using a timer, however i do not necessarily understand how to use a timer to wait.
I set up my timer to be 2 seconds, but when i run this code the last call runs without a 2 second delay.
Timer timer = new Timer();
timer.Tick += new EventHandler(timer_Tick); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000) * (2); // Timer will tick evert second
timer.Enabled = true; // Enable the timer
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "first";
timer.Start();
label1.Text = "second";
}
So when i click my button, it immediately shows label1 as "second", as opposed to changing to "first", waiting 2 seconds, then changing to "second". I have read lots of threads here about using timers instead of thread.sleep, but i cannot seem to find/figure out how to actually implement that.
timer.Start()
just starts the timer but immediately returns while the timer is running in the background. So between setting the label text tofirst
and tosecond
there is nearly no pause. What you want to do is wait for the timer to tick and only then update the label again:Btw. you should not set
timer.Enabled
to true, you are already starting the timer usingtimer.Start()
.As mentioned in the comments, you could put the timer creation into a method, like this (note: this is untested):
And then you could just use it like this:
Tergiver’s follow-up
Usually lambdas do not cause problems for the garbage collection. In this case, the timer instance only exists locally and the reference in the lambda does not prevent the garbage collection to collect the instances (see also this question).
I actually tested this again using the .NET Memory Profiler. The timer objects were collected just fine, and no leaking happened. The profiler did give me a warning that there are instances that “[…] have been garbage collected without being properly disposed” though. Removing the event handler in itself (by keeping a reference to it) did not fix that though. Changing the captured timer reference to
(Timer)s
did not change that either.What did help—obviously—was to call a
timer.Dispose()
in the event handler after stopping the timer, but I’d argue if that is actually necessary. I don’t think the profiler warning/note is that critical.If you're using C# 5.0
await
makes this much easier:If all you're trying to do is change the text when the timer ticks, would you not be better off putting...
...In the timer tick, either before or after you change the timer to enabled = false;
Like so;