8

Possible Duplicate:
Background Worker Check For When It's Midnight?

Is there a SystemEvent which I can register to and which will be published at midnight, when the Date has changed?

Community
  • 1
  • 1
BennoDual
  • 5,865
  • 15
  • 67
  • 153

2 Answers2

14

Here's a class I use to handle this. It's similar to @sll's answer, however takes into account the system time changing and also will trigger each midnight instead of only once.

static class MidnightNotifier
{
    private static readonly Timer timer;

    static MidnightNotifier()
    {
        timer = new Timer(GetSleepTime());
        timer.Elapsed += (s, e) =>
        {
            OnDayChanged();
            timer.Interval = GetSleepTime();
        };
        timer.Start();

        SystemEvents.TimeChanged += OnSystemTimeChanged;
    }

    private static double GetSleepTime()
    {
        var midnightTonight = DateTime.Today.AddDays(1);
        var differenceInMilliseconds = (midnightTonight - DateTime.Now).TotalMilliseconds;
        return differenceInMilliseconds;
    }

    private static void OnDayChanged()
    {
        var handler = DayChanged;
        if (handler != null)
            handler(null, null);
    }

    private static void OnSystemTimeChanged(object sender, EventArgs e)
    {
        timer.Interval = GetSleepTime();
    }

    public static event EventHandler<EventArgs> DayChanged;
}

Since it's a static class, you can subscribe to the event using code like:

MidnightNotifier.DayChanged += (s, e) => { Console.WriteLine("It's midnight!"); };
Ben Hoffstein
  • 102,129
  • 8
  • 104
  • 120
  • Doesn't take into account the system time changing and won't trigger after the "first" midnight (although not clear whether the questioner wants that). – Ben Hoffstein Dec 12 '11 at 20:28
  • 1
    +1 Right, `SystemEvents.TimeChanged` is a good catch! – sll Dec 12 '11 at 20:31
2

The Windows Task Scheduler is generally the proper way to start something at a specified date.

But if you are really searching for an event or equivalent:

var timer = new System.Timers.Timer((DateTime.Today.AddDays(1) – DateTime.Now).
    TotalMillisecond);
timer.Elapsed += new ElapsedEventHandler(OnMidnight);
timer.Start();
Otiel
  • 18,404
  • 16
  • 78
  • 126
  • This won't work since timer will raise Elapsed event almost each second – sll Dec 12 '11 at 20:11
  • @sll: How's that? `(DateTime.Today.AddDays(1) – DateTime.Now).Millisecond)` is the number of ms until midnight. – Otiel Dec 12 '11 at 20:13
  • 3
    No, Milliseconds would return a value of milliseconds of a timespan, you need `TotalMilliseconds` value instead. You can check it - give it a try – sll Dec 12 '11 at 20:15