I have a method that uses Timer class to call on a method and execute it on specific intervals.
private Timer tmr = new Timer();
public void WorkAtInterval(long interval, Action<object> work)
{
//heartbeat in miliseconds
tmr.Interval = interval;
tmr.Start();
tmr.Elapsed += new ElapsedEventHandler(work);
}
I have defined the function that has to be called like this:
private static void WorkSample (object interval)
{
Console.WriteLine("The interval is: {0}",interval);
}
and then eventually in my Main function:
static void Main(string[] args)
{
HeartBeat heart = new HeartBeat();
var interval = heart.HeartBeatInterval;
heart.WorkAtInterval(interval,sampleWork(interval));
Console.Read();
}
unfortunately, this even is not compiling. I am not that great with delegates.Any recommendation on how I can get this to work?
You can use a lambda expression:
heart.WorkAtInterval(interval, x => WorkSample(interval));
The solution is like this. The signature of the WorkAtInterval has to meet the signature ElapsedEventHandler. And then in the Main function the calling has to be done properly by anonymous function.
public void WorkAtInterval(long interval, Action<object,EventArgs> work)
{
//heartbeat in miliseconds
tmr.Interval = interval;
tmr.Start();
tmr.Elapsed += new ElapsedEventHandler(work);
}
private static void sampleWork(object interval)
{
Console.WriteLine("The interval is: {0}",interval);
}
static void Main(string[] args)
{
HeartBeat heart = new HeartBeat();
var interval = heart.HeartBeatInterval;
heart.WorkAtInterval(interval,(o,s) => sampleWork(interval));
Console.Read();
}
Related
I have a class with timer like below
public class helper
{
Timer timer = new Timer();
private int counter = 0;
private int returnCode = 0;
public int Process()
{
SetTimer();
Console.WriteLine("The application started ");
return counter;
}
public void SetTimer()
{
int optionalWay = 0;
// Create a timer with a two second interval.
timer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e, optionalWay);
timer.AutoReset = true;
timer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
{
counter++;
Console.WriteLine("Timer is ticking");
if (counter == 10)
{
timer.Stop();
timer.Dispose();
returnCode = returnCode + 1;
}
}
}
I have main function like this below
public static void Main()
{
helper helper = new helper();
int code = helper.Process();
Console.WriteLine("Main " + code.ToString());
Console.ReadLine();
}
what I want to do is return to main when my timer is stopped, not before that
, my timer class is running fine, main is getting printed like below
So main should wait till the result from timer is 1. And then end process
The code is working as it should. There is nothing inside the helper.Process() function that can wait or block the execution, so the function is returning immediately to the main before the OnTimedEvent is even executed.
A workaround can be done by implementing an event in the helper class and raise that event after the timer completes its work. And the main can listen to that event and act accordingly.
public class helper
{
Timer timer = new Timer();
private int counter = 0;
private int returnCode = 0;
public event EventHandler<int> Done;
...
private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
{
counter++;
Console.WriteLine("Timer is ticking");
if (counter == 10)
{
timer.Stop();
timer.Dispose();
returnCode = returnCode + 1;
if (Done != null)
{
Done.Invoke(this, returnCode);
}
}
}
}
And in the Program.cs
static void Main(string[] args)
{
helper helper = new helper();
helper.Done += helper_Done;
helper.Process();
Console.ReadLine();
}
static void helper_Done(object sender, int e)
{
Console.WriteLine("Main " + e.ToString());
}
Update
The Timer class uses a new thread from ThreadPool to execute the Elapsed event handler. So it cannot return to the Main which is running on a different thread. In short: what you are trying to do cannot not be achieved with a Timer.
Here is another solution using Thread.Sleep() which will satisfy your requirement, but keep in mind using Thread.Sleep() like this is not recommended.
public class helper
{
private int counter = 0;
private int returnCode = 0;
public int Process()
{
Console.WriteLine("The application started ");
StartTimer(2000);
return returnCode;
}
private void StartTimer(int ms)
{
while (counter++ < 10)
{
System.Threading.Thread.Sleep(ms);
Console.WriteLine("Timer is ticking");
}
returnCode = returnCode + 1;
}
}
class Program
{
static void Main(string[] args)
{
helper helper = new helper();
int code = helper.Process();
Console.WriteLine("Main " + code.ToString());
Console.ReadLine();
}
}
Again, this is NOT a good practice to use Thread.Sleep for a delayed execution and Thread.Sleep is less accurate compare to Timer.Elapsed. Try to change the design of your application and use Event or Callback function.
Change the Process function of helper class to accept a callback:
public void Process(Action<int> callBack)
{
SetTimer();
Console.WriteLine("The application started ");
if (timer != null)
timer.Disposed += (o, e) => callBack(counter);
}
Change the main function to send the callback:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
helper helper = new helper();
helper.Process(c => Console.WriteLine("Main " + c.ToString()));
Console.ReadLine();
}
I have two options in mind, one of them and the ugliest, is to loop until timer is stopped, basically doing so:
public class helper
{
Timer timer = new Timer();
private int counter = 0;
private int returnCode = 0;
private bool timerWorking = false;
public int Process()
{
SetTimer();
Console.WriteLine("The application started ");
while(timerWorking){}
return counter;
}
public void SetTimer()
{
// All the staff you already have
timerWorking = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
{
counter++;
Console.WriteLine("Timer is ticking");
if (counter == 10)
{
//All the staff you already have
timerWorking = false;
}
}
}
Or, the more elegant, passing or registering a callback to be executed once the ending point is reached:
public class helper
{
Timer timer = new Timer();
private int counter = 0;
private int returnCode = 0;
Action<int> _doAfterTimerEnds
public void Process(Action<int> doAfterTimerEnds)
{
SetTimer();
_doAfterTimerEnds = doAfterTimerEnds;
Console.WriteLine("The application started ");
}
public void SetTimer()
{
int optionalWay = 0;
// Create a timer with a two second interval.
timer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e, optionalWay);
timer.AutoReset = true;
timer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
{
counter++;
Console.WriteLine("Timer is ticking");
if (counter == 10)
{
timer.Stop();
timer.Dispose();
returnCode = returnCode + 1;
_doAfterTimerEnds(returnCode)
}
}
}
public static void Main()
{
var returnCode = 0;
var helper = new helper();
helper.Process(code => returnCode = code);
while (returnCode != 1) {}
Console.WriteLine("Main " + returnCode);
Console.ReadLine();
}
UPDATE: I've tested this last version and it is working as expected.
How can I get a C# method to run on a timer? I found this example online but the DoStuffOnTimer() method below is not getting hit:
public void DoStuff()
{
var intervalMs = 5000;
var timer = new Timer(intervalMs);
timer.Elapsed += new ElapsedEventHandler(DoStuffOnTimer);
timer.Enabled = true;
}
private void DoStuffOnTimer(object source, ElapsedEventArgs e)
{
//do stuff
}
Or if you don't need very precise timer you always can create it yourself:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Temp
{
internal class Program
{
// this is the `Timer`
private static async Task CallWithInterval(Action action, TimeSpan interval, CancellationToken token)
{
while (true)
{
await Task.Delay(interval, token);
if (token.IsCancellationRequested)
{
return;
}
action();
}
}
// your method which is called with some interval
private static void DoSomething()
{
Console.WriteLine("ding!");
}
// usage sample
private static void Main()
{
// we need it to add the ability to stop timer on demand at any time
var cts = new CancellationTokenSource();
// start Timer
var task = CallWithInterval(DoSomething, TimeSpan.FromSeconds(1), cts.Token);
// continue doing another things - I stubbed it with Sleep
Thread.Sleep(5000);
// if you need to stop timer, let's try it!
cts.Cancel();
// check out, it really stopped!
Thread.Sleep(2000);
}
}
}
using System;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program thisone = new Program();
thisone.DoStuff();
Console.Read();
}
public void DoStuff()
{
var intervalMs = 5000;
Timer timer = new Timer(intervalMs);
timer.Elapsed += new ElapsedEventHandler(DoStuffOnTimer);
timer.Enabled = true;
}
private void DoStuffOnTimer(object source, ElapsedEventArgs e)
{
//do stuff
Console.WriteLine("Tick!");
}
}
}
I am new to C# but java has method to execute specified task at the specified time so using c# how it doing
Timer t=new Timer();
TimerTask task1 =new TimerTask()
t.schedule(task1, 3000);
You can get a complete tutorial of how timer works in C# here : http://www.dotnetperls.com/timer
In Short:
using System;
using System.Collections.Generic;
using System.Timers;
public static class TimerExample // In App_Code folder
{
static Timer _timer; // From System.Timers
static List<DateTime> _l; // Stores timer results
public static List<DateTime> DateList // Gets the results
{
get
{
if (_l == null) // Lazily initialize the timer
{
Start(); // Start the timer
}
return _l; // Return the list of dates
}
}
static void Start()
{
_l = new List<DateTime>(); // Allocate the list
_timer = new Timer(3000); // Set up the timer for 3 seconds
//
// Type "_timer.Elapsed += " and press tab twice.
//
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true; // Enable it
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_l.Add(DateTime.Now); // Add date on each timer event
}
}
Using Anonymous Methods and Object Initializer:
var timer = new Timer { Interval = 5000 };
timer.Tick += (sender, e) =>
{
MessageBox.Show(#"Hello world!");
};
Here is a sample:
public class Timer1
{
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 5 seconds.
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!");
}
}
using System;
using System.Threading;
namespace ConsoleApplication6
{
class Program
{
public void TimerTask(object state)
{
//Do your task
Console.WriteLine("oops");
}
static void Main(string[] args)
{
var program = new Program();
var timer = new Timer(program.TimerTask,
null,
3000,
Timeout.Infinite);
Thread.Sleep(10000);
}
}
}
I have a maze game and I'm trying to create two Timers at a time.
1st (Exits the game after 300 secs)
t1.Interval = 30000;
t1.Enabled = true;
t1.Elapsed += new ElapsedEventHandler(hiddenTimer);
public static void hiddenTimer(object source, ElapsedEventArgs e)
{
Console.Clear();
Environment.Exit(1);
}
2nd (Displays the time remaining every 1 sec (like a real timer))
t2.Interval = 1000;
t2.Enabled = true;
t2.Elapsed += new ElapsedEventHandler(showTimer);
public static void showTimer(object source, ElapsedEventArgs e)
{
Console.Write(timeLeft);
}
I would want to pass declare timeLeft globally but it says that "An object reference is required for the non-static field, method, or property..."
How would I declare it properly?
By making a static property:
public static Double TimeLeft { get; set; }
This is if you want to Publicliy accessable from your entire context, if you want it private, just change public to private.
Just a side note, the built in Timer doesn't support polling for the remaining time until the next elapse. Either you decrease TimeLeft in each Elapse-event on the 1sec timer or you can have a look at this.
Edit
Here is one way to do it with one timer, first I declare two properties and one constant field that I use, don't bother that they are static, it's just easier to run it as a console application this way.
public static Timer SystemTimer { get; set; }
public static double Elapsed { get; set; }
private const double CycleInterval = 1000;
Then in my Main-method I have the following to initiate my Timer
SystemTimer = new Timer();
SystemTimer.Interval = CycleInterval;
SystemTimer.Enabled = true;
SystemTimer.Elapsed += Cycle;
SystemTimer.Start();
Having this, the Cycle-event handler can look like this:
static void Cycle(object sender, ElapsedEventArgs e)
{
Elapsed += CycleInterval;
if ((Elapsed%5000) == 0.0)
{
Console.WriteLine("5 sec elapsed!");
// Do stuff each 5 sec
}
if ((Elapsed % 10000) == 0.0)
{
Console.WriteLine("10 sec elapsed!");
// Do stuff each 10 sec
}
Console.WriteLine("Elapsed: {0}", Elapsed);
}
You could also have Elapsed being a TimeSpan, but you can refactor this as you like.
Here's my complete source code that I used:
using System;
using System.IO;
using System.Timers;
namespace ConsoleApplication5
{
class Program
{
public static Timer SystemTimer { get; set; }
public static double Elapsed { get; set; }
private const double CycleInterval = 1000;
static void Main(string[] args)
{
SystemTimer = new Timer();
SystemTimer.Interval = CycleInterval;
SystemTimer.Enabled = true;
SystemTimer.Elapsed += Cycle;
SystemTimer.Start();
while (true) ;
}
static void Cycle(object sender, ElapsedEventArgs e)
{
Elapsed += CycleInterval;
if ((Elapsed%5000) == 0.0)
{
Console.WriteLine("5 sec elapsed!");
// Do stuff each 5 sec
}
if ((Elapsed % 10000) == 0.0)
{
Console.WriteLine("10 sec elapsed!");
// Do stuff each 10 sec
}
Console.WriteLine("Elapsed: {0}", Elapsed);
}
}
}
And this is what it looks like when I run it:
First of all, you should declare your timeLeft as a static if you want it to behave like a global variable.
Secondly I'd use one timer and keep track of the time separately for each event:
static DateTime startTime = DateTime.Now;
static DateTime lastTime = DateTime.Now;
In your timer, which should be set to something to give more accuracy like 1/10 of a second, do this:
if (DateTime.Now - lastTime > new TimeSpan(0, 0, 1))
// Update the time here for your 1s clock
lastTime = DateTime.Now;
if (DateTime.Now - startTime > new TimeSpan(0, 0, 300))
// Exit the game
Your timings will be more accurate this way.
Mark it static:
public static int TimeLeft;
Your timeLeft memeber is not static.
Make it static or make showTimer method non static.
Regards.
I'm not really writing an alarm clock application, but it will help to illustrate my question.
Let's say that I have a method in my application, and I want this method to be called every hour on the hour (e.g. at 7:00 PM, 8:00 PM, 9:00 PM etc.). I could create a Timer and set its Interval to 3600000, but eventually this would drift out of sync with the system clock. Or I could use a while() loop with Thread.Sleep(n) to periodically check the system time and call the method when the desired time is reached, but I don't like this either (Thread.Sleep(n) is a big code smell for me).
What I'm looking for is some method in .Net that lets me pass in a future DateTime object and a method delegate or event handler, but I haven't been able to find any such thing. I suspect there's a method in the Win32 API that does this, but I haven't been able to find that, either.
Or, you could create a timer with an interval of 1 second and check the current time every second until the event time is reached, if so, you raise your event.
You can make a simple wrapper for that :
public class AlarmClock
{
public AlarmClock(DateTime alarmTime)
{
this.alarmTime = alarmTime;
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = 1000;
timer.Start();
enabled = true;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(enabled && DateTime.Now > alarmTime)
{
enabled = false;
OnAlarm();
timer.Stop();
}
}
protected virtual void OnAlarm()
{
if(alarmEvent != null)
alarmEvent(this, EventArgs.Empty);
}
public event EventHandler Alarm
{
add { alarmEvent += value; }
remove { alarmEvent -= value; }
}
private EventHandler alarmEvent;
private Timer timer;
private DateTime alarmTime;
private bool enabled;
}
Usage:
AlarmClock clock = new AlarmClock(someFutureTime);
clock.Alarm += (sender, e) => MessageBox.Show("Wake up!");
Please note the code above is very sketchy and not thread safe.
Interesting, I've actually come across a very similar issue and went looking for a method in the .Net framework that would handle this scenario. In the end, we ended up implementing our own solution that was a variation on a while loop w/ Thread.Sleep(n) where n gets smaller the closer you get to the desired target time (logarithmically actually, but with some reasonable thresholds so you're not maxing the cpu when you get close to the target time.) Here's a really simple implementation that just sleeps half the time between now and the target time.
class Program
{
static void Main(string[] args)
{
SleepToTarget Temp = new SleepToTarget(DateTime.Now.AddSeconds(30),Done);
Temp.Start();
Console.ReadLine();
}
static void Done()
{
Console.WriteLine("Done");
}
}
class SleepToTarget
{
private DateTime TargetTime;
private Action MyAction;
private const int MinSleepMilliseconds = 250;
public SleepToTarget(DateTime TargetTime,Action MyAction)
{
this.TargetTime = TargetTime;
this.MyAction = MyAction;
}
public void Start()
{
new Thread(new ThreadStart(ProcessTimer)).Start();
}
private void ProcessTimer()
{
DateTime Now = DateTime.Now;
while (Now < TargetTime)
{
int SleepMilliseconds = (int) Math.Round((TargetTime - Now).TotalMilliseconds / 2);
Console.WriteLine(SleepMilliseconds);
Thread.Sleep(SleepMilliseconds > MinSleepMilliseconds ? SleepMilliseconds : MinSleepMilliseconds);
Now = DateTime.Now;
}
MyAction();
}
}
You could simply reset the timer duration each time it fires, like this:
// using System.Timers;
private void myMethod()
{
var timer = new Timer {
AutoReset = false, Interval = getMillisecondsToNextAlarm() };
timer.Elapsed += (src, args) =>
{
// Do timer handling here.
timer.Interval = getMillisecondsToNextAlarm();
timer.Start();
};
timer.Start();
}
private double getMillisecondsToNextAlarm()
{
// This is an example of making the alarm go off at every "o'clock"
var now = DateTime.Now;
var inOneHour = now.AddHours(1.0);
var roundedNextHour = new DateTime(
inOneHour.Year, inOneHour.Month, inOneHour.Day, inOneHour.Hour, 0, 0);
return (roundedNextHour - now).TotalMilliseconds;
}
You could create an Alarm class which has a dedicated thread which goes to sleep until the specified time, but this will use the Thread.Sleep method. Something like:
/// <summary>
/// Alarm Class
/// </summary>
public class Alarm
{
private TimeSpan wakeupTime;
public Alarm(TimeSpan WakeUpTime)
{
this.wakeupTime = WakeUpTime;
System.Threading.Thread t = new System.Threading.Thread(TimerThread) { IsBackground = true, Name = "Alarm" };
t.Start();
}
/// <summary>
/// Alarm Event
/// </summary>
public event EventHandler AlarmEvent = delegate { };
private void TimerThread()
{
DateTime nextWakeUp = DateTime.Today + wakeupTime;
if (nextWakeUp < DateTime.Now) nextWakeUp = nextWakeUp.AddDays(1.0);
while (true)
{
TimeSpan ts = nextWakeUp.Subtract(DateTime.Now);
System.Threading.Thread.Sleep((int)ts.TotalMilliseconds);
try { AlarmEvent(this, EventArgs.Empty); }
catch { }
nextWakeUp = nextWakeUp.AddDays(1.0);
}
}
}
I know it's a bit of an old question, but I came across this when I was looking for an answer to something else. I thought I'd throw my two cents in here, since I recently had this particular issue.
Another thing you can do is schedule the method like so:
/// Schedule the given action for the given time.
public async void ScheduleAction ( Action action , DateTime ExecutionTime )
{
try
{
await Task.Delay ( ( int ) ExecutionTime.Subtract ( DateTime.Now ).TotalMilliseconds );
action ( );
}
catch ( Exception )
{
// Something went wrong
}
}
Bearing in mind it can only wait up to the maximum value of int 32 (somewhere around a month), it should work for your purposes. Usage:
void MethodToRun ( )
{
Console.WriteLine ("Hello, World!");
}
void CallingMethod ( )
{
var NextRunTime = DateTime.Now.AddHours(1);
ScheduleAction ( MethodToRun, NextRunTime );
}
And you should have a console message in an hour.
What about System.Timers.Timer class ? See http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
I have used this before with great success:
Vb.net:
Imports System.Threading
Public Class AlarmClock
Public startTime As Integer = TimeOfDay.Hour
Public interval As Integer = 1
Public Event SoundAlarm()
Public Sub CheckTime()
While TimeOfDay.Hour < startTime + interval
Application.DoEvents()
End While
RaiseEvent SoundAlarm()
End Sub
Public Sub StartClock()
Dim clockthread As Thread = New Thread(AddressOf CheckTime)
clockthread.Start()
End Sub
End Class
C#:
using System.Threading;
public class AlarmClock
{
public int startTime = TimeOfDay.Hour;
public int interval = 1;
public event SoundAlarmEventHandler SoundAlarm;
public delegate void SoundAlarmEventHandler();
public void CheckTime()
{
while (TimeOfDay.Hour < startTime + interval) {
Application.DoEvents();
}
if (SoundAlarm != null) {
SoundAlarm();
}
}
public void StartClock()
{
Thread clockthread = new Thread(CheckTime);
clockthread.Start();
}
}
I don't know if the c# works, but the vb works just fine.
Usage in VB:
Dim clock As New AlarmClock
clock.interval = 1 'Interval is in hours, could easily convert to anything else
clock.StartClock()
Then, just add an event handler for the SoundAlarm event.