using System; using System.Runtime.InteropServices; namespace DataService { public class MediaTimer : IDisposable { //Lib API declarations [DllImport("Winmm.dll", CharSet = CharSet.Auto)] static extern uint timeSetEvent(uint uDelay, uint uResolution, TimerCallback lpTimeProc, UIntPtr dwUser,uint fuEvent); [DllImport("Winmm.dll", CharSet = CharSet.Auto)] static extern uint timeKillEvent(uint uTimerID); [DllImport("Winmm.dll", CharSet = CharSet.Auto)] static extern uint timeGetTime(); [DllImport("Winmm.dll", CharSet = CharSet.Auto)] static extern uint timeBeginPeriod(uint uPeriod); [DllImport("Winmm.dll", CharSet = CharSet.Auto)] static extern uint timeEndPeriod(uint uPeriod); //Timer type definitions [Flags] public enum fuEvent : uint { TIME_ONESHOT = 0, //Event occurs once, after uDelay milliseconds. TIME_PERIODIC = 1, TIME_CALLBACK_FUNCTION = 0x0000, /* callback is function */ TIME_CALLBACK_EVENT_SET = 0x0010, /* callback is event - use SetEvent */ TIME_CALLBACK_EVENT_PULSE = 0x0020 /* callback is event - use PulseEvent */ } //Delegate definition for the API callback delegate void TimerCallback(uint uTimerID, uint uMsg, UIntPtr dwUser, UIntPtr dw1, UIntPtr dw2); //IDisposable code private bool disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { Stop(); } } disposed = true; } ~MediaTimer() { Dispose(false); } /// /// The current timer instance ID /// uint id = 0; /// /// The callback used by the the API /// TimerCallback thisCallBack; /// /// The timer elapsed event /// public event EventHandler Timer; public MediaTimer() { //Initialize the API callback thisCallBack = CallBackFunc; } /// /// Stop the current timer instance (if any) /// public void Stop() { lock (this) { if (id != 0) { timeKillEvent(id); //Debug.WriteLine("MMTimer " + id.ToString() + " stopped"); id = 0; } } } /// /// Start a timer instance /// /// Timer interval in milliseconds /// If true sets a repetitive event, otherwise sets a one-shot public void Start(uint ms, bool repeat) { //Kill any existing timer Stop(); //Set the timer type flags fuEvent f = fuEvent.TIME_CALLBACK_FUNCTION | (repeat ? fuEvent.TIME_PERIODIC : fuEvent.TIME_ONESHOT); lock (this) { id = timeSetEvent(ms, 0, thisCallBack, UIntPtr.Zero, (uint)f); if (id == 0) { throw new Exception("timeSetEvent error"); } //Debug.WriteLine("MMTimer " + id.ToString() + " started"); } } void CallBackFunc(uint uTimerID, uint uMsg, UIntPtr dwUser, UIntPtr dw1, UIntPtr dw2) { //Callback from the MMTimer API that fires the Timer event. Note we are in a different thread here if (Timer != null) { Timer(this, new EventArgs()); } } } }