Unstoppable Timer - c#

I'm attempting to make a "simple" timer from 15 minutes to 0 seconds. I'm using 900 seconds as my 15 minutes. When I Run the program it runs through fine but Continues going into the negatives. I'm still a novice at C#. I'm wanting the code to stop at 0 and run an alert to grab someone's attention. Here is what I have thus far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
namespace GBS_GI_Timer
{
public class Program
{
public static int t = 2;
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
//Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
//GC.KeepAlive(aTimer);
if (t == 0)
aTimer.Stop();
}
public static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//TimeSpan timeRemaining = TimeSpan.FromSeconds(t);
Console.WriteLine("Time remianing..{0}", t);
t--;
if (t == 0)
{
Console.WriteLine("\a");
Console.WriteLine("Time to check their vitals, again!");
Console.WriteLine("Press any key to exit...");
}
// Console.ReadKey();
Console.ReadLine();
}
}
}

You have it coded so that when you hit enter (or type something and hit enter), it then checks t and may stop the timer. You're checking if t == 0 and only then stopping the timer. What happens if t is less than zero before you hit enter?

You would have to refactor your code as below to make it work, System.Timers.Timer used ThreadPool to run the callback routines.
class Program
{
public static int t = 2;
static System.Timers.Timer aTimer = new System.Timers.Timer();
public static void Main()
{
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
Console.ReadLine();
}
public static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Time remianing..{0}", t);
t--;
if (t == 0)
{
Console.WriteLine("\a");
Console.WriteLine("Time to check their vitals, again!");
Console.WriteLine("Press any key to exit...");
aTimer.Stop();
Console.ReadLine();
}
}
}

There are some other logic issues with your program as it stands, and I am not certain it would do what you want even if it was running, though.
I would refactor your OnTimedEvent to just do
Console.WriteLine(string.Format("{0} time to check their vitals!"));
and use a while loop to check the status of t in the main routine.
You could also change the Timer.Interval when entering the handler so that no other events fire until they acknowledge the first event, but then you couldn't guarantee that this routine runs for 15 minutes...

Related

Alarm clock using Thread.Sleep

Here I have a code of an alarm clock:
public static void Main(string[] args)
{
Console.Write("Seconds: ");
int seconds = int.Parse(Console.ReadLine());
System.Threading.Thread.Sleep(seconds * 1000);
Timer timer = new Timer(100);
timer.Elapsed += MakeSound;
timer.Enabled = true;
GC.KeepAlive(timer);
Console.ReadLine();
}
private static void MakeSound(object sender, ElapsedEventArgs e)
{
Console.Beep();
}
As you can see, it doesn't look so promising because I am using Thread.Sleep.
It still works if I use
Timer timer = new Timer(seconds * 1000); instead of System.Threading.Thread.Sleep(seconds * 1000);
But it doesn't beep constantly, just between interval of seconds * 1000 seconds until user presses Enter. Can I make it any better?
If you look at the constructor overloads for System.Threading.Timer, you'll see that you can specify the dueTime, as well as the period: https://msdn.microsoft.com/en-us/library/2x96zfy7(v=vs.110).aspx
So, instead of using System.Threading.Thread.Sleep(1000 * seconds), use
Timer timer = new Timer(new TimerCallback(MakeSound), null, 1000 * seconds, 100);

Halting program execution until a timer stops

I want to produce some text in a console window for a certain amount of time before clearing it and showing more text. I thought the following code would do that, but instead, after the timer expires, the console is cleared but no other text appears.
Is this the correct way to halt program execution until a timer expires?
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
Timer peekTimer = new Timer (SECOND * PEEK_TIME);
peekTimer.Elapsed += onTimerTick;
peekTimer.AutoReset = false;
peekTimer.Start ();
Console.WriteLine ("Timer started...");
while (peekTimer.Enabled) { }
Console.WriteLine ("Timer done.");
Console.ReadLine ();
}
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
Console.Clear ();
}
Here is codesample using the Thread.Sleep function.
using System;
using System.Threading;
namespace ConsoleApplication
{
public class Program
{
public static void Main()
{
Console.WriteLine("Timer Start!");
Thread.Sleep(5000);
Console.Clear();
Console.WriteLine("End");
Console.ReadKey();
}
}
}
You don't need timer for this:
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
var task = Task.Run(()=>
{
Console.WriteLine ("Work started...");
Thread.Sleep(PEEK_TIME*SECOND);
Console.Clear();
});
task.Wait();
Console.WriteLine ("Work done.");
Console.ReadLine ();
}
In your onTimerTick event, you need to stop the timer (or set peekTimer.Enabled == false) if you want the while loop to exit:
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
Console.Clear ();
peekTimer.Stop();
}
In order to do this, you'll have to declare the timer at a wider scope so you can access it from your Main method and from the Tick event handler:
namespace ConsoleApplication
{
timer peekTimer;
public class Program
{
In answer to your larger question, this is not the best way to do it. If you're just going to sit and do nothing for a specific amount of time, you might as well just put the thread to sleep rather than spinning around the whole time:
Console.WriteLine("Waiting 5 seconds...");
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine("...Time's up!!");
In my game I use this approach:
public static Timer peekTimer = new Timer (SECOND * PEEK_TIME);
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
Console.WriteLine ("Timer started...");
peekTimer.Interval = new TimeSpan(0, 0, 0, 0, SECOND * PEEK_TIME);
peekTimer.Tick += new EventHandler(onTimerTick);
peekTimer.Start();
}
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
peekTimer.Stop();
Console.Clear ();
Console.WriteLine ("Timer done.");
Console.ReadLine ();
}

Trouble using timer class in C#

basically I'm trying to implement the timer in class for my would-be very first game in C#; I want to use timers that will constantly update the player and provide certain periodic feedback, but I can't seem to get the 'timer' class to work correctly. If I use it in a loop (as shown below), it will wait 2 seconds, and then keep writing "You're Alive!" to the console with 0 delay in-between; and if I do not use the loop, the application just ends instantly.
using System;
using System.Timers;
public class MyClass
{
public static void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("You're alive!");
}
public static void Main(String[] args)
{
while (true)
{
Timer MyTimer = new Timer();
MyTimer.Interval = 2000;
MyTimer.Enabled = true;
MyTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
MyTimer.Start();
}
}
Just add below line after MyTimer.Start();
Console.ReadLine();
static void Main(String[] args)
{
Timer MyTimer = new Timer();
MyTimer.Interval = 2000;
MyTimer.Enabled = true;
MyTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
MyTimer.Start();
Console.ReadLine();
}
private static void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("You're alive!");
}

Only raise an event if the previous one was completed

I'm using a System.Timers.Timer in my application. Every second I run a function which does some job. The thing is, this function can block for some little time (it reads then processes a large file from disk). I want to start that function only if its previous "execution instance" has completed. I thought I could achieve this with a Mutex:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static Mutex TimerMut = new Mutex(false);
public static void Main()
{
Thread TT = new Thread(new ThreadStart(delegate()
{
System.Timers.Timer oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}));
TT.Start();
Console.Read();
}
private static void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
TimerMut.WaitOne();
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
TimerMut.ReleaseMutex();
}
}
}
That doesn't work, "foos" still appear every second. How can I achieve this?
EDIT: You're right, it makes no sense to start a new thread to handle this. I thought only System.Threading.Timer is launched in a separate thread.
I'm not sure why you are using a new thread to start the timer, since timers run on their own thread, but here's a method that works. Simply turn the timer off until you are done with the current interval.
static System.Timers.Timer oTimer
public static void Main()
{
oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}
private void Handler(object oSource, ElapsedEventArgs oElapsedEventArgs)
{
oTimer.Enabled = false;
Console.WriteLine("foo");
Thread.Sleep(5000); //simulate some work
Console.WriteLine("bar");
oTimer.Enabled = true;
}
If you want to skip the tick if another is already working you can do this.
private readonly object padlock = new object();
private void SomeMethod()
{
if(!Monitor.TryEnter(padlock))
return;
try
{
//Do heavy work
}
finally
{
Monitor.Exit(padlock);
}
}
Easiest way I know of to do this kind of thing:
internal static volatile bool isRunning;
public static void Main()
{
Thread TT = new Thread(new ThreadStart(delegate()
{
System.Timers.Timer oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}));
TT.Start();
}
private void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
if(isRunning) return;
isRunning = true;
try
{
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
}
finally { isRunning = false; }
}
The handler still runs, but the very first thing it does is make sure that another handler isn't running, and if one is, it stops immediately.
For timers executing handlers more quickly (like 3-4 times a second), this has the possibility to race; two threads could proceed past the guard clause before one of them sets the bit. You can avoid this with a couple of lock statements, similar to a Mutex or Monitor:
static object syncObj = new object();
private void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
lock(syncObj)
{
if(isRunning) return;
isRunning = true;
}
try
{
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
}
finally { lock(syncObj) { isRunning = false; } }
}
This will ensure that only one thread can ever be examining or modifying isRunning, and as isRunning is marked volatile, the CLR won't cache its value as part of each thread's state for performance; each thread has to look at exactly the same memory location to examine or change the value.
You can follow the following pattern to skip doing the indicated work if another invocation of this method is still running:
private int isWorking = 0;
public void Foo()
{
if (Interlocked.Exchange(ref isWorking, 1) == 0)
{
try
{
//Do work
}
finally
{
Interlocked.Exchange(ref isWorking, 0);
}
}
}
The approach that you were using with a Mutex will result in addition ticks waiting for earlier ticks to finish, not skipping invocations when another is still running, which is what you said you wanted. (When dealing with timers like this its common to want to skip such ticks, not wait. If your tick handlers regularly take too long you end up with a giant queue of waiting handlers.)

Offset Timer starts

Hi new to the site so I apologize if my question is not properly formatted
If i have two events that need to alternate every 2 seconds (one is ON the other is OFF), how can i delay the start of one of the timers for the 2 second offset?
static void Main(string[] args)
{
Timer aTimer = new Timer();
Timer bTimer = new Timer();
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
bTimer.Elapsed += new ElapsedEventHandler(OnTimedEventb);
// Set the Interval to 4 seconds
aTimer.Interval = 4000;
aTimer.Enabled = true;
bTimer.Interval = 4000;
bTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The status is on {0}", e.SignalTime);
}
private static void OnTimedEventb(object source, ElapsedEventArgs b)
{
Console.WriteLine("The state is off {0}", b.SignalTime);
}
So I basically want the ON event to happen when the program starts, then 2 seconds later have the OFF event fire and so on
using vs 2012 console app but I will be using in windows forms program
You can create a class level bool called IsOn, for example, and toggle that. You only need one timer to do this as true would mean it's on and false would mean it's off.
private static bool IsOn = true; //default to true (is on)
static void Main(string[] args)
{
Timer aTimer = new Timer();
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
IsOn = !IsOn;
Console.WriteLine("The status is {0} {1}", IsOn.ToString(), e.SignalTime);
}

Categories

Resources