That's very nice, however in order to simulate some time passing we need to run a command that takes some time and that's very clear in second example.
However, the style of using a for loop to do some functionality forever takes a lot of device resources and instead we can use the Garbage Collector to do some thing like that.
We can see this modification in the code from the same book CLR Via C# Third Ed.
using System;
using System.Threading;
public static class Program
{
private Timer _timer = null;
public static void Main()
{
// Create a Timer object that knows to call our TimerCallback
// method once every 2000 milliseconds.
_timer = new Timer(TimerCallback, null, 0, 2000);
// Wait for the user to hit <Enter>
Console.ReadLine();
}
private static void TimerCallback(Object o)
{
// Display the date/time when this method got called.
Console.WriteLine("In TimerCallback: " + DateTime.Now);
}
}
Use the System.Threading.Timer class.
System.Windows.Forms.Timer is designed primarily for use in a single thread usually the Windows Forms UI thread.
There is also a System.Timers class added early on in the development of the .NET framework. However it is generally recommended to use the System.Threading.Timer class instead as this is just a wrapper around System.Threading.Timer anyway.
It is also recommended to always use a static (shared in VB.NET) System.Threading.Timer if you are developing a Windows Service and require a timer to run periodically. This will avoid possibly premature garbage collection of your timer object.
Here's an example of a timer in a console application:
using System;
using System.Threading;
public static class Program
{
public static void Main()
{
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, 5, 0, 2000);
Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // Simulating other work (10 seconds)
t.Dispose(); // Cancel the timer now
}
// This method's signature must match the TimerCallback delegate
private static void ComputeBoundOp(Object state)
{
// This method is executed by a thread pool thread
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // Simulates other work (1 second)
// When this method returns, the thread goes back
// to the pool and waits for another task
}
}
From the book CLR Via C# by Jeff Richter. By the way this book describes the rationale behind the 3 types of timers in Chapter 23, highly recommended.
Here is the code to create a simple one second timer tick:
using System;
using System.Threading;
class TimerExample
{
static public void Tick(Object stateInfo)
{
Console.WriteLine("Tick: {0}", DateTime.Now.ToString("h:mm:ss"));
}
static void Main()
{
TimerCallback callback = new TimerCallback(Tick);
Console.WriteLine("Creating timer: {0}\n",
DateTime.Now.ToString("h:mm:ss"));
// create a one second timer tick
Timer stateTimer = new Timer(callback, null, 0, 1000);
// loop here forever
for (; ; )
{
// add a sleep for 100 mSec to reduce CPU usage
Thread.Sleep(100);
}
}
}
And here is the resulting output:
c:\temp>timer.exe
Creating timer: 5:22:40
Tick: 5:22:40
Tick: 5:22:41
Tick: 5:22:42
Tick: 5:22:43
Tick: 5:22:44
Tick: 5:22:45
Tick: 5:22:46
Tick: 5:22:47
EDIT: It is never a good idea to add hard spin loops into code as they consume CPU cycles for no gain. In this case that loop was added just to stop the application from closing, allowing the actions of the thread to be observed. But for the sake of correctness and to reduce the CPU usage a simple Sleep call was added to that loop.
Lets Have A little Fun
using System;
using System.Timers;
namespace TimerExample
{
class Program
{
static Timer timer = new Timer(1000);
static int i = 10;
static void Main(string[] args)
{
timer.Elapsed+=timer_Elapsed;
timer.Start(); Console.Read();
}
private static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
i--;
Console.Clear();
Console.WriteLine("=================================================");
Console.WriteLine(" DEFUSE THE BOMB");
Console.WriteLine("");
Console.WriteLine(" Time Remaining: " + i.ToString());
Console.WriteLine("");
Console.WriteLine("=================================================");
if (i == 0)
{
Console.Clear();
Console.WriteLine("");
Console.WriteLine("==============================================");
Console.WriteLine(" B O O O O O M M M M M ! ! ! !");
Console.WriteLine("");
Console.WriteLine(" G A M E O V E R");
Console.WriteLine("==============================================");
timer.Close();
timer.Dispose();
}
GC.Collect();
}
}
}
Or using Rx, short and sweet:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
You can also use your own timing mechanisms if you want a little more control, but possibly less accuracy and more code/complexity, but I would still recommend a timer. Use this though if you need to have control over the actual timing thread:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
would be your timing thread(modify this to stop when reqiuired, and at whatever time interval you want).
and to use/start you can do:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Callback is your void parameterless method that you want called at each interval. For example:
private void CallBack()
{
//Do Something.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With