Alarm clock application in .Net

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();
    }
}

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.


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;
}