How to call a particular method every some seconds in c#? - c#

"Robot Game" is the first basic game I developed. The Magenta '#' character is an enemy and it is supposed have a random movement in this map, but its random movement is too fast and I tried to use Threading but it effects all characters' speed. Now, I need To call the "Enemy" method every 100 milliseconds.
Robot game Image:

You can use System.Timer. However, be forewarned that these timers might not be as accurate as you may desire. You'll never easily get a fully-accurate timer on a non-realtime OS such as Windows, but if you want better timer accuracy, a Multimedia timer might help.
System.Timer example from MSDN:
public class Timer1
{
private static System.Timers.Timer aTimer;
public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}

Related

C# Pause Program Execution

I am writing a program that will perform an operation every 10 or 15 minutes. I want it to be running all the time, so I need something that is cheap on processing power. What I have read so far seems to suggest that I want to use a Timer. Here is a clip of the code I have so far.
class Program {
private static Timer timer = new Timer();
static void Main(string[] args) {
timer.Elapsed += new ElapsedEventHandler(DoSomething);
while(true) {
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
}
}
}
The problem here is that the while loop just keeps executing rapidly. How do I halt execution until the timer is elapsed. My program really doesn't need to be multi threaded. Is a Timer the right tool for this job?
Thank you in advance for any help!
UPDATE: Sorry for the confusion. I have implemented the DoSomething method. I just did not include it as I don't believe it is part of my issue.
Timer's will fire off the Elapsed event once the specified interval has elapsed.
I would do something like this:
private static Timer timer = new Timer();
static void Main(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(DoSomething);
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
Console.ReadKey(); //Wait for keypress to terminate
}
You could also implement this as a service so you don't have to have a blocking call like Console.ReadKey to keep the program from terminating.
Finally, you could just change the interval in the event handler:
static void DoSomething(...)
{
timer.Stop();
timer.Interval = TimerMilliseconds();
...
timer.Start();
}
The problem with this code is that you're using a loop to set the Interval and Enabled properties of the Timer, which will execute said assignments over and over - it's not waiting for the timer to execute in some way.
If your application doesn't need to be mutlithreaded, then you might be better simply calling Thread.Sleep between executions.
class Program {
static void Main(string[] args) {
while(true) {
Thread.sleep(TimerMilliseconds()); // The duration of the wait will differ each time
DoSomething();
}
}
}
take out the timer and loop from your logic. Just use windows scheduler to execute your program after 15 minutes. Or you can use windows services. Please read Best Timer for using in a Windows service
remove the while loop completely.
inside of the DoSomething() function (once implemented) stop timer at start and at the end reset the interval before restarting the timer.
I guess the comments and answrs already provide the hints you need, but the MSDN docs for Timer actually provide a nice example. In my opinion the Timer approach is a bit tidier, it's easier to read your intentions and abstracts away the details of invoking your scheduled code.
Here's another alternative approach using ManualResetEvent and WaitOne(). This will allow you to halt the main thread without worrying about it being killed accidentally by an errant keypress. You can also Set() the MRE when certain conditions are met to allow the app to exit gracefully:
class Program
{
private static Timer timer;
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
timer = new Timer(TimerCallback, null, 0, (int)TimeSpan.FromMinutes(15).TotalMilliseconds);
mre.WaitOne();
}
private static void TimerCallback(object state)
{
// ... do something in here ...
Console.WriteLine("Something done at " + DateTime.Now.ToString());
}
}

How do I do an infinite loop in C# with a 1 minute delay per iteration?

How do I execute an infinite loop in C# with a 1 minute delay per iteration?
Is there any way to do it without using some kind of variable with x++ and setting x to some incredibly large number?
Solution1 :
If you want to wait for 1 minute without hanging your Main Thread, it is good to use Timer Control.
Step 1: You need to Subscribe to the Timer Tick event.
Step 2: Set the Interval property of the Timer to 60000 milliseconds for raising the event for every Minute.
Step 3: In Tick Event Handler just do ehatever you want to perform.
Step 4: you can Call the timer1.Stop() method whenever you want to stop the timer.
Note : if you don't stop the timer it becomes infinite.
if you want to stop the timer you can call timer1.Stop();
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
timer1.Interval=60000;//one minute
timer1.Tick += new System.EventHandler(timer1_Tick);
timer1.Start();
private void timer1_Tick(object sender, EventArgs e)
{
//do whatever you want
}
Solution 2:
EDIT : From the below comments : if the OP(Original Poster) is Trying to run this from Console Application System.Timers.Timer can be used
Note : instead of Handling Tick Event , OP has to handle the Elapsed Event.
Complete Code:
class Program
{
static System.Timers.Timer timer1 = new System.Timers.Timer();
static void Main(string[] args)
{
timer1.Interval = 60000;//one minute
timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Tick);
timer1.Start();
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
static private void timer1_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
//do whatever you want
Console.WriteLine("I'm Inside Timer Elapsed Event Handler!");
}
}
while (true)
{
System.Threading.Thread.Sleep(60000);
}
Now if we assume you don't want this thread to block and you're ok dealing with threading concerns, you can do something like this:
System.Threading.Tasks.Task.Run(() =>
{
while (true)
{
// do your work here
System.Threading.Thread.Sleep(60000);
}
});
The Task will put your work on a ThreadPool thread, so it runs in the background.
You can also look at a BackgroundWorker if that's more geared toward what you want.
for(;;)
{
//do your work
Thread.Sleep(60000);
}
This is not optimal but does exactly what it's asked.
From a similar question on MSDN:
>
System.Threading.Thread.Sleep(5000);
this codes make your application waiting for 5 seconds.
Change the number as necessary for the amount of time you want to sleep for (for one minute, this would be 60000).
You can put this where you want in your while loop
while(true){
Sleep(60000);}
This would be a blocking call, so you would want to put it on its own thread or any kind of UI that you would have would hang badly.
Sleep is in the System.Threading.Thread namespace.

What is the best way to implement a "timer"? [duplicate]

This question already has answers here:
How do you add a timer to a C# console application
(12 answers)
Closed 3 years ago.
What is the best way to implement a timer? A code sample would be great! For this question, "best" is defined as most reliable (least number of misfires) and precise. If I specify an interval of 15 seconds, I want the target method invoked every 15 seconds, not every 10 - 20 seconds. On the other hand, I don't need nanosecond accuracy. In this example, it would be acceptable for the method to fire every 14.51 - 15.49 seconds.
Use the Timer class.
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
aTimer.Enabled = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read() != 'q');
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Hello World!");
}
The Elapsed event will be raised every X amount of milliseconds, specified by the Interval property on the Timer object. It will call the Event Handler method you specify. In the example above, it is OnTimedEvent.
By using System.Windows.Forms.Timer class you can achieve what you need.
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 15000; // specify interval time as you want
t.Tick += new EventHandler(timer_Tick);
t.Start();
void timer_Tick(object sender, EventArgs e)
{
//Call method
}
By using stop() method you can stop timer.
t.Stop();
It's not clear what type of application you're going to develop (desktop, web, console...)
The general answer, if you're developing Windows.Forms application, is use of
System.Windows.Forms.Timer class. The benefit of this is that it runs on UI thread, so it's simple just define it, subscribe to its Tick event and run your code on every 15 second.
If you do something else then windows forms (it's not clear from the question), you can choose System.Timers.Timer, but this one runs on other thread, so if you are going to act on some UI elements from the its Elapsed event, you have to manage it with "invoking" access.
Reference ServiceBase to your class and put the below code in the OnStartevent:
Constants.TimeIntervalValue = 1 (hour)..Ideally you should set this value in config file.
StartSendingMails = function name you want to run in the application.
protected override void OnStart(string[] args)
{
// It tells in what interval the service will run each time.
Int32 timeInterval = Int32.Parse(Constants.TimeIntervalValue) * 60 * 60 * 1000;
base.OnStart(args);
TimerCallback timerDelegate = new TimerCallback(StartSendingMails);
serviceTimer = new Timer(timerDelegate, null, 0, Convert.ToInt32(timeInterval));
}

Intensive Stop/Start of a C# Timer

I've created a watchdog timer (using a System.Windows.Forms.Timer), which triggers if a long period of time expires without receiving a small packet of data:
using System.Windows.Forms;
public class Watchdog
{
private Timer Timer;
public void Go()
{
Timer.Start();
}
public void Reset()
{
Timer.Stop();
Timer.Start();
}
private void OnTimerExpired(object State)
{
Timer.Stop();
DoSomething();
}
public Watchdog()
{
Timer = new Timer();
Timer.Tick += new EventHandler(OnTimerExpired);
Timer.Interval = (1000 * Timeout);
}
}
The main code calls Go(), and then calls Reset() each time a packet is received. If the timer expires, OnTimerExpired() is called.
Since that there may be hundreds of packet receptions per second, and since the main job of the application is to respond to such packets, I'm beginning to wonder if resetting the timer isn't too CPU/OS intensive.
Any idea how calling Timer.Stop()/Timer.Start() this way may impact performance (in terms of latency)?
Use a simple timespan or integer variable as a flag. When the timer ticks, it checks against a Stopwatch object to see how much time has elapsed since the flag was last udpated. If it's longer than your timeout value you trigger your watchdog code.
Now, instead of resetting your timer, other code can just use the stopwatch to update your timespan flag value when a new packet comes in.
You should also either set your timer's tick interval to about 1/2 of what you want the actual timeout duration to be, or have code in the event to set your interval so your next tick event is just a few milliseconds after you would timeout if the connection was severed now. Otherwise you could end up waiting almost twice as long as the timeout duration in the situation where your last packet arrived very soon after a tick event.
Another option, by the way, is to just have a Boolean flag that's set whenever a message comes in. The timer event handler checks that flag and alerts if it's not set. So you have:
private bool GotAMessage = false;
void MessageReceived()
{
// happens whenever a message is received
GotAMessage = true;
}
void OnTimerExpired(object state)
{
if (!GotAMessage)
{
// didn't receive a message in time.
}
GotAMessage = false;
}
A simpler option is to call a method on the WatchDog class that updates a common lastPacketReceived value time a packet is received. Then you only need to start a single timer one time in the WatchDog class that ticks once per timeout interval and compares the current time to the lastPacketReceived value:
public static class WatchDog
{
static object locker = new object();
static long lastPacketReceived;
static Stopwatch stopWatch = new Stopwatch();
static long threshold = 5000;
static WatchDog()
{
Timer watchDogTimer = new Timer(1000);
watchDogTimer.Elapsed += new ElapsedEventHandler(watchDogTimer_Elapsed);
watchDogTimer.Start();
stopWatch.Start();
}
static void watchDogTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (locker)
{
if ((stopWatch.ElapsedMilliseconds - lastPacketReceived) > threshold)
{
// threshold exceeded
}
}
}
public static void PacketReceived()
{
lock (locker)
{
lastPacketReceived = stopWatch.ElapsedMilliseconds;
}
}
}
Any idea how calling Timer.Stop()/Timer.Start()
This way may impact performance (in terms of latency)?
None
The amount of resources required to do this is unlikely to be measured. Unless you have a performance problem, don't try to solve a performance problem, at the very least use software to profile the software to see if its an actual problem.

Timer elapsed event firing twice in C# command line program

My timer 'Elapsed' event fires twice when the program is started. The only assignment of the 'Elapsed' event handler is in 'Main' method. Is there something that I'm doing wrong?
//class level clock
public static System.Timers.Timer Clock;
static void Main(string[] args)
{
Clock = new System.Timers.Timer();
Clock.Elapsed += new ElapsedEventHandler(Clock_Elapsed);
Clock.AutoReset = false;
Clock.Interval = timerInterval; //this needs to be in milliseconds!
Clock.Enabled = true;
//run infinite loop until q is pressed
while (Console.Read() != 'q')
{}
}
static void Clock_Elapsed(object sender, ElapsedEventArgs e)
{
Clock.Stop();
//do some stuff
Clock.Start();
}
UPDATE:
The AutoReset provided by #fparadis2 fixed the firing twice. The base issue was that my timer interval was set to 30 milliseconds instead of 30000 milliseconds(30 seconds) so that the event was double firing.
If timerInverval is small enough, it might be possible that the Elapsed event is fired twice before you get the chance to stop the clock. You should do
Clock.AutoReset = false;
in order to be notified only once each time you start the timer.
As specified in the Timer Class documentation:
If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
You may also consider checking this pattern.

Categories