Skip to content

Instantly share code, notes, and snippets.

@IanSavchenko
Created January 1, 2018 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IanSavchenko/0d5e761719627ba2683ba15347db4071 to your computer and use it in GitHub Desktop.
Save IanSavchenko/0d5e761719627ba2683ba15347db4071 to your computer and use it in GitHub Desktop.
UWP Clock

Clock service for UWP

The snippet allows to get notifications when a minute number changes on a clock. So if you have a clock displayed in your app, but don't have seconds displayed, you don't need to maintain 1s interval timer. Just subscribe to event and unsubscribe when not needed.

Application suspending is handled additionnaly, because it makes timers stop. That's why when app is resumed, a Delayed clock tick event will happen.

Of course, there can be a second-based event, if needed. The service will still be useful, because it performs timer management.

using System;
using System.Threading;
using Windows.ApplicationModel;
using Windows.UI.Xaml;
namespace IanSavchenko.Services
{
/// <summary>
/// Provides real time clock events.
/// </summary>
public class ClockService
{
private readonly object _subscriptionLock = new object();
private EventHandler<ClockTickEventArgs> _minuteEventHandler;
private Timer _minuteTimer;
/// <summary>
/// Invoked every minute, when minute changes on a clock
/// </summary>
public event EventHandler<ClockTickEventArgs> MinuteTick
{
add
{
lock (_subscriptionLock)
{
_minuteEventHandler += value;
EnableMinuteTicks();
}
}
remove
{
lock (_subscriptionLock)
{
_minuteEventHandler -= value;
if (_minuteEventHandler == null)
DisableMinuteTicks();
}
}
}
private void EnableMinuteTicks()
{
if (_minuteTimer != null)
return;
InitTimer();
Application.Current.Suspending += AppOnSuspending;
Application.Current.Resuming += AppOnResuming;
}
private void DisableMinuteTicks()
{
if (_minuteTimer == null)
return;
_minuteTimer.Dispose();
_minuteTimer = null;
Application.Current.Suspending -= AppOnSuspending;
Application.Current.Resuming -= AppOnResuming;
}
private void InitTimer()
{
_minuteTimer = new Timer(OnMinuteTick, null, TimeSpan.FromSeconds(60 - DateTime.Now.Second), TimeSpan.FromMinutes(1));
}
private void OnMinuteTick(object arg)
{
_minuteEventHandler?.Invoke(this, new ClockTickEventArgs(DateTime.Now, ClockTickType.Normal));
}
private void AppOnSuspending(object sender, SuspendingEventArgs suspendingEventArgs)
{
_minuteTimer.Change(-1, -1);
_minuteTimer.Dispose();
}
private void AppOnResuming(object sender, object e)
{
InitTimer();
_minuteEventHandler?.Invoke(this, new ClockTickEventArgs(DateTime.Now, ClockTickType.Delayed));
}
}
/// <summary>
/// Clock tick event payload
/// </summary>
public class ClockTickEventArgs
{
public ClockTickEventArgs(DateTime time, ClockTickType clockTickType)
{
Time = time;
ClockTickType = clockTickType;
}
public ClockTickType ClockTickType { get; private set; }
public DateTime Time { get; private set; }
}
/// <summary>
/// Type of tick event
/// </summary>
public enum ClockTickType
{
/// <summary>
/// Event was invoked in real time or close to it
/// </summary>
Normal,
/// <summary>
/// Event was invoked with a delay, because it couldn't be invoked in real time
/// </summary>
Delayed,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment