I am trying to repeat a code execution after predefined time passes and i don't want to mess up things by using threads. Is the below code a good practice?
Stopwatch sw = new Stopwatch(); // sw constructor
EXIT:
// Here I have my code
sw.Start();
while (sw.ElapsedMilliseconds < 100000)
{
// do nothing, just wait
}
System.Media.SystemSounds.Beep.Play(); // for test
sw.Stop();
goto EXIT;
Use a timer instead of labels and StopWatch. You are doing busy waiting, tying up the CPU in that tight loop.
You start a timer, giving it an interval to fire on (100000 milliseconds), then run your code in the event handler for the Tick event.
See Comparing the Timer Classes in the .NET Framework Class Library in MSDN magazine.
You could use a timer what Oded suggested:
public partial class TestTimerClass : Form
{
Timer timer1 = new Timer(); // Make the timer available for this class.
public TestTimerClass()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Tick += timer1_Tick; // Assign the tick event
timer1.Interval = 1000; // Set the interval of the timer in ms (1000 ms = 1 sec)
timer1.Start(); // Start the timer
}
void timer1_Tick(object sender, EventArgs e)
{
System.Media.SystemSounds.Beep.Play();
timer1.Stop(); // Stop the timer (remove this if you want to loop the timer)
}
}
EDIT: Just want to show you how to make an easy timer if you don't know how to :)
Related
I'm trying to figure out how to make it so, after lets say, 1 minute so 60000 milliseconds the console will say hi.
All I have so far is
System.Timers.Timer timer = new System.Timers.Timer(60000);
timer.Start();
But I don't know how to make it so when the timer is done, it will do something.
You can use the elapse event, when 60000 ms has pass the event will be thrown. Example of the elapse event:
class Program
{
static void Main(string[] args)
{
System.Timers.Timer timer = new System.Timers.Timer(60000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(elapse); // subscribing to the elapse event
timer.Start(); // start Timer
Console.ReadLine(); // hold compiler until key pressed
}
private static void elapse(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Hy");
}
}
or
void Main()
{
var t = new System.Threading.Timer((s)=>Console.WriteLine("Hi"),null,0,60000);
Console.ReadLine();
}
You can use System.Threading.Thread.Sleep if you only want to do the write once (the timer will run every x seconds):
System.Threading.Thread.Sleep(60000);
Console.WriteLine("something");
What you will want to do is create an event that writes to the console when the timer has elapsed the predefined amount of time.
This is done as follows:
Start by creating your timer and set it to 60s:
var timer = new System.Timers.Timer(60000); //60seconds
Next create an event that will be triggered when the time has elapsed:
private static void MyEvent(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Hello World");
}
Next, bind the timer to that event:
timer.Elapsed += MyEvent;
What this does is tell the computer that when the timer actually starts running in the future and then the timer elapses (60s passes after the timer starts), then the Event called 'MyEvent' will be called which writes to the console.
Finally Start the timer:
timer.Start();
And wait for the even to trigger and write to the console.
I have a function in winform that is executed every x time (eg. every 60 minutes).
And then it does some stuff, then I want it to wait some seconds (using a timer) and then execute do some stuff part2.
private void goToFtp(int time)
{
double interval = time* 60 * 1000;
System.Timers.Timer checkForTime = new System.Timers.Timer(interval);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
}
System.Windows.Forms.Timer timerDelayWatcher = new System.Windows.Forms.Timer();
private void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
.......Do some stuff part1
timerDelayWatcher.Tick += new EventHandler(timerDelayWatcher_Tick); // Everytime timer ticks, timer_Tick will be called
timerDelayWatcher.Interval = (1000) * (5);
timerDelayWatcher.Enabled = true;
timerDelayWatcher.Start();
}
private void timerDelayWatcher_Tick(object sender, EventArgs e)
{
timerDelayWatcher.Stop();
.......Do some stuff part2
}
The problem is that the timerDelayWatcher_Tick is not fired...any ideias why?
You need use:
Thread.Sleep(5000);
But first you need add
using System.Threading;
or use
System.Threading.Thread.Sleep(5000);
on 5000 are the time in milliseconds
Sample
private void timerDelayWatcher_Tick(object sender, EventArgs e)
{
timerDelayWatcher.Stop();
System.Threading.Thread.Sleep(5000);
.......Do some stuff part2
}
Try calling the start method on the system.timers.timer firstly, and I would recommend sticking to one type of timer, and pattern of use, say use the system.timer.timer and do the work you need on elapsed, then restart with and wait for the next elapsed event.
Either that or I would suggest looking at the task library and async flow in .net 4/4.5 and as #Ferri suggests using a Sleep
Take also care on loosing reference to the class containing the timerDelayWatcher member.
If it happens the timer is disposed so no more events...
I want to show timer on UI such that when aplication star executing timer starts with 00:00:00 and when it completed its execution timer stops. Timer should show timing per second while running.
You can use the System.Windows.Forms.Timer, which is created for scenarios like yours. You can read more about in MSDN.
You should use the following code snippet as sample:
Timer timer = new Timer();
timer.Interval = 1000;
timer.Tick += new System.EventHandler(timer_Tick);
timer.Start();
private void timer_Tick(object sender, System.EventArgs e)
{
this.Text = string.Format("{0:hh:MM:ss}", DateTime.Now);
}
Notice that you should dispose the Timer when you do not needed.
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.
If you're using C# 5.0 await makes this much easier:
private async void button1_Click(object sender, EventArgs e)
{
label1.Text = "first";
await Task.Delay(2000);
label1.Text = "second";
}
timer.Start() just starts the timer but immediately returns while the timer is running in the background. So between setting the label text to first and to second there is nearly no pause. What you want to do is wait for the timer to tick and only then update the label again:
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
label1.Text = "second";
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "first";
timer.Start();
}
Btw. you should not set timer.Enabled to true, you are already starting the timer using timer.Start().
As mentioned in the comments, you could put the timer creation into a method, like this (note: this is untested):
public void Delayed(int delay, Action action)
{
Timer timer = new Timer();
timer.Interval = delay;
timer.Tick += (s, e) => {
action();
timer.Stop();
};
timer.Start();
}
And then you could just use it like this:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "first";
Delayed(2000, () => label1.Text = "second");
}
Tergiver’s follow-up
Does using Delayed contain a memory leak (reference leak)?
Subscribing to an event always creates a two-way reference.
In this case timer.Tick gets a reference to an anonymous function (lambda). That function lifts a local variable timer, though it's a reference, not a value, and contains a reference to the passed in Action delegate. That delegate is going to contain a reference to label1, an instance member of the Form. So is there a circular reference from the Timer to the Form?
I don't know the answer, I'm finding it a bit difficult to reason about. Because I don't know, I would remove the use of the lambda in Delayed, making it a proper method and having it, in addition to stopping the timer (which is the sender parameter of the method), also remove the event.
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 all you're trying to do is change the text when the timer ticks, would you not be better off putting...
label1.Text = "second";
...In the timer tick, either before or after you change the timer to enabled = false;
Like so;
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
label1.Text = "second";
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "first";
timer.Start();
}
private bool Delay(int millisecond)
{
Stopwatch sw = new Stopwatch();
sw.Start();
bool flag = false;
while (!flag)
{
if (sw.ElapsedMilliseconds > millisecond)
{
flag = true;
}
}
sw.Stop();
return true;
}
bool del = Delay(1000);
I want to raise a function periodically .
When I finish one function cycle to wait some period of time and only them to start the second run.
I thought to make it like :
timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Enabled = true;
timer.Start();
timer.Elapsed += TimerTick;
private void TimerTick(object sender, EventArgs e)
{
//My functionality
}
But seems that TimerTick is raised every secound and not secound from my last TimerTick run .
How i can solve this one ?
You can use threads:
var thread = new Thread(o => {
while(true)
{
DoTick();
Thread.Sleep(1000);
}
});
You can stop your timer before doing your processing and start it again after it's done:
private void TimerTick(object sender, EventArgs e)
{
timer.Stop();
//My functionality
timer.Start();
}
it's also a good idea to put your functionality in a try-catch and call Start() in the finally section. (if this suits you)
Try the following:
private void TimerTick(object sender, EventArgs e)
{
// get the timer that raised this event (you can have multiple
// timers, or the timer obj is out of scope here, so use this):
Timer timer = (Timer) sender;
// disable (or use timer.Stop())
timer.Enabled = false;
// ...
// your code
// ...
// at end, re-enable
timer.Enabled = true;
}
you will find that the timer will now run 1000ms after your code finished. You can also use timer.Stop() and timer.Start().
you could always do something like this:
while (true)
{
// your functions
Thread.Sleep(1000)
}
you'd have to find a way to stop this through an external mechanism, but it should work.
You're right: the timer will run every second: it won't care what you're doing in the TimerTick.
What you can do is to stop the timer on entering the TimerTick methode.
private void TimerTick(object sender, EventArgs e)
{
timer.Stop();
//My functionality
timer.Start();
}
Try this:
DateTime lastDT = DateTime.MinValue;
private void TimerTick(object sender, EventArgs e)
{
DateTime now = DateTime.Now;
if (now - last).TotalSeconds > what_you_want
{
//My functionality
}
last = now;
}
Using this, your form (main thread) is not locked and you/user can do what you please.
Try
private void TimerTick(object sender, EventArgs e)
{
timer.Stop();
// My Functionality
timer.Stop();
}
However, you may have an extra even fired. As per MSDN Docs:
The signal to raise the Elapsed event is always queued for execution on a ThreadPool thread, so the event-handling method might run on one thread at the same time that a call to the Stop method runs on another thread. This might result in the Elapsed event being raised after the Stop method is called. The code example in the next section shows one way to work around this race condition.
You might want to consider Thread.Sleep() instead