Timer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / WinForms / Managed / System / WinForms / Timer.cs / 1 / Timer.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Windows.Forms {
    using System.Threading; 
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics; 
    using System.Windows.Forms.Design;
    using System; 
    using System.Globalization; 

    ///  
    /// 
    ///    Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for
    ///       use in Win Forms
    ///       applications and must be used in a window. 
    /// 
    [ 
    DefaultProperty("Interval"), 
    DefaultEvent("Tick"),
    ToolboxItemFilter("System.Windows.Forms"), 
    SRDescription(SR.DescriptionTimer)
    ]
    public class Timer : Component {
 
        /// 
        ///  
        ///  
        private int interval;
 
        /// 
        /// 
        /// 
        private bool enabled; 

        ///  
        ///  
        /// 
        private EventHandler onTimer; 

        /// 
        /// 
        ///  
        private GCHandle timerRoot;
 
 
        // our holder for the HWND that handles our Timer messages.
        // 
        private TimerNativeWindow timerWindow;

        /// 
        ///  
        /// 
        private object userData; 
 
        private object syncObj = new object();
 
        /// 
        /// 
        /// Initializes a new instance of the 
        /// class. 
        /// 
        public Timer() 
        : base() { 
            interval = 100;
        } 

        /// 
        /// 
        /// Initializes a new instance of the  class with the specified container. 
        /// 
        public Timer(IContainer container) : this() { 
            container.Add(this); 
        }
 
        /// 
        [
        SRCategory(SR.CatData),
        Localizable(false), 
        Bindable(true),
        SRDescription(SR.ControlTagDescr), 
        DefaultValue(null), 
        TypeConverter(typeof(StringConverter)),
        ] 
        public object Tag {
            get {
                return userData;
            } 
            set {
                userData = value; 
            } 
        }
 
        /// 
        /// 
        ///    Occurs when the specified timer
        ///       interval has elapsed and the timer is enabled. 
        /// 
        [SRCategory(SR.CatBehavior), SRDescription(SR.TimerTimerDescr)] 
        public event EventHandler Tick { 
            add {
                onTimer += value; 
            }
            remove {
                onTimer -= value;
            } 
        }
 
       ///  
        /// 
        ///     
        ///       Disposes of the resources (other than memory) used by the timer.
        ///    
        /// 
        protected override void Dispose(bool disposing) { 
            if (disposing) {
                if (timerWindow != null) { 
                    timerWindow.StopTimer(); 
                }
 
                Enabled = false;
            }
            timerWindow = null;
            base.Dispose(disposing); 
        }
 
        ///  
        /// 
        ///     Indicates whether the timer is 
        ///       running.
        /// 
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.TimerEnabledDescr) 
        ] 
        public virtual bool Enabled {
            get { 
                if (timerWindow == null) {
                    return enabled;
                }
                return  timerWindow.IsTimerRunning; 
            }
 
            set { 
                lock(syncObj) {
 
                    if (enabled != value) {

                        enabled = value;
 
                        // At runtime, enable or disable the corresponding Windows timer
                        // 
                        if (!DesignMode) { 
                            if (value) {
 
                                // create the timer window if needed.
                                //
                                if (timerWindow == null) {
 
                                    timerWindow = new TimerNativeWindow(this);
                                } 
 
                                timerRoot = GCHandle.Alloc(this);
 
                                timerWindow.StartTimer(interval);
                            }
                            else{
                                if (timerWindow != null){ 
                                    timerWindow.StopTimer();
                                } 
 
                                if (timerRoot.IsAllocated) {
                                    timerRoot.Free(); 
                                }

                            }
                        } 

 
                    } 
                }
 
            }
        }

        ///  
        /// 
        ///     
        ///       Indicates the time, in milliseconds, between timer ticks. 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(100),
        SRDescription(SR.TimerIntervalDescr)
        ] 
        public int Interval {
            get { 
                return interval; 
            }
            set { 
                lock(syncObj) {
                    if (value < 1)
                        throw new ArgumentOutOfRangeException("Interval", SR.GetString(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture)));
 
                    if (interval != value) {
                        interval = value; 
                        if (Enabled) { 

                            Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?"); 
                            // just change the timer value, don't tear down the timer
                            // itself.
                            //
                            if (!DesignMode && timerWindow != null) { 
                                timerWindow.RestartTimer(value);
                            } 
                        } 
                    }
                } 
            }
        }

        ///  
        /// 
        /// Raises the  
        /// event. 
        /// 
        protected virtual void OnTick(EventArgs e) { 
            if (onTimer != null) onTimer(this, e);
        }

        ///  
        /// 
        ///    Starts the 
        ///       timer. 
        /// 
        public void Start() { 
            Enabled = true;
        }

        ///  
        /// 
        ///    Stops the 
        ///       timer. 
        /// 
        public void Stop() { 
            Enabled = false;
        }

        ///  
        /// 
        ///     returns us as a string. 
        ///  
        /// 
        public override string ToString() { 
            string s = base.ToString();
            return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture);
        }
 

        private class TimerNativeWindow : NativeWindow { 
 

            // the timer that owns us 
            //
            private Timer _owner;

            // our current id -- this is usally the same as TimerID but we also 
            // use it as a flag of when our timer is running.
            // 
            private int   _timerID; 

            // arbitrary timer ID. 
            //
            private static int    TimerID = 1;

            // setting this when we are stopping the timer so someone can't restart it in the process. 
            //
            private bool _stoppingTimer; 
 
            internal TimerNativeWindow(Timer owner) {
 
                this._owner = owner;
            }

            ~TimerNativeWindow() { 

 
 

                // note this call will work form the finalizer thread. 
                //
                StopTimer();
            }
 
            public bool IsTimerRunning {
                get { 
 
                    return _timerID != 0 && Handle != IntPtr.Zero;
                } 
            }


            // Ensures that our HWND has been created. 
            //
            private bool EnsureHandle() { 
                if (Handle == IntPtr.Zero) { 

 
                    // we create a totally vanilla invisible window just for WM_TIMER messages.
                    //
                    CreateParams cp = new CreateParams();
                    cp.Style = 0; 
                    cp.ExStyle = 0;
                    cp.ClassStyle = 0; 
                    cp.Caption = GetType().Name; 

                    // Message only windows are cheaper and have fewer issues than 
                    // full blown invisible windows.  But, they are only supported
                    // on NT.
                    if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
                        cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; 
                    }
 
                    CreateHandle(cp); 
                }
                Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!"); 
                return Handle != IntPtr.Zero;
            }

            // Returns true if we need to marshal across threads to access this timer's HWND. 
            //
            private bool GetInvokeRequired(IntPtr hWnd) { 
                if (hWnd != IntPtr.Zero) { 
                    int pid;
                    int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid); 
                    int currentThread = SafeNativeMethods.GetCurrentThreadId();
                    return(hwndThread != currentThread);
                }
                return false; 
            }
 
            // change the interval of the timer without destroying the HWND. 
            //
            public void RestartTimer(int newInterval) { 
                StopTimer(false, IntPtr.Zero);
                StartTimer(newInterval);
            }
 
            // Start the timer with the specified interval.
            // 
            public void StartTimer(int interval) { 

                if (_timerID == 0 && !_stoppingTimer) { 
                    if (EnsureHandle()) {
                        _timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero);
                    }
                } 
            }
 
            // stop the timer. 
            //
            public void StopTimer() { 

                StopTimer(true, IntPtr.Zero);
            }
 
            // stop the timer and optionally destroy the HWND.
            // 
            public void StopTimer(bool destroyHwnd, IntPtr hWnd) { 

 
                if (hWnd == IntPtr.Zero) {

                    hWnd = Handle;
                } 

                // Fire a message across threads to destroy the timer and HWND on the thread that created it. 
                // 
                if (GetInvokeRequired(hWnd)) {
                    UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0); 
                    return;
                }

                // Locking 'this' here is ok since this is an internal class.  See VSW#464499. 
                lock(this) {
 
                    if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) { 

                        return; 
                    }

                    if (_timerID != 0) {
 

                        try { 
                            _stoppingTimer = true; 
                            SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID);
                        } 
                        finally {
                            _timerID = 0;
                            _stoppingTimer = false;
                        } 

                    } 
 
                    if (destroyHwnd) {
                        base.DestroyHandle(); 
                    }
                }
            }
 
            // Destroy the handle, stopping the timer first.
            // 
            public override void DestroyHandle() { 
                // don't recurse!
                // 
                StopTimer(false, IntPtr.Zero);
                Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
                base.DestroyHandle();
            } 

            protected override void OnThreadException(Exception e) { 
                Application.OnThreadException(e); 
            }
 
            public override void ReleaseHandle() {
                // don't recurse!
                //
                StopTimer(false, IntPtr.Zero); 
                Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
 
                base.ReleaseHandle(); 
            }
 
            protected override void WndProc(ref Message m) {

                Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?");
 
                // for timer messages, make sure they're ours (it'll be wierd if they aren't)
                // and call the timer event. 
                // 
                if (m.Msg == NativeMethods.WM_TIMER) {
                    //Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?"); 
                    if ((int)m.WParam == _timerID) {
                        _owner.OnTick(EventArgs.Empty);
                        return;
                    } 
                }
                else if (m.Msg == NativeMethods.WM_CLOSE) { 
                    // this is a posted method from another thread that tells us we need 
                    // to kill the timer.  The handle may already be gone, so we specify it here.
                    // 
                    StopTimer(true, m.HWnd);
                    return;
                }
                base.WndProc(ref m); 
            }
 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Windows.Forms {
    using System.Threading; 
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics; 
    using System.Windows.Forms.Design;
    using System; 
    using System.Globalization; 

    ///  
    /// 
    ///    Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for
    ///       use in Win Forms
    ///       applications and must be used in a window. 
    /// 
    [ 
    DefaultProperty("Interval"), 
    DefaultEvent("Tick"),
    ToolboxItemFilter("System.Windows.Forms"), 
    SRDescription(SR.DescriptionTimer)
    ]
    public class Timer : Component {
 
        /// 
        ///  
        ///  
        private int interval;
 
        /// 
        /// 
        /// 
        private bool enabled; 

        ///  
        ///  
        /// 
        private EventHandler onTimer; 

        /// 
        /// 
        ///  
        private GCHandle timerRoot;
 
 
        // our holder for the HWND that handles our Timer messages.
        // 
        private TimerNativeWindow timerWindow;

        /// 
        ///  
        /// 
        private object userData; 
 
        private object syncObj = new object();
 
        /// 
        /// 
        /// Initializes a new instance of the 
        /// class. 
        /// 
        public Timer() 
        : base() { 
            interval = 100;
        } 

        /// 
        /// 
        /// Initializes a new instance of the  class with the specified container. 
        /// 
        public Timer(IContainer container) : this() { 
            container.Add(this); 
        }
 
        /// 
        [
        SRCategory(SR.CatData),
        Localizable(false), 
        Bindable(true),
        SRDescription(SR.ControlTagDescr), 
        DefaultValue(null), 
        TypeConverter(typeof(StringConverter)),
        ] 
        public object Tag {
            get {
                return userData;
            } 
            set {
                userData = value; 
            } 
        }
 
        /// 
        /// 
        ///    Occurs when the specified timer
        ///       interval has elapsed and the timer is enabled. 
        /// 
        [SRCategory(SR.CatBehavior), SRDescription(SR.TimerTimerDescr)] 
        public event EventHandler Tick { 
            add {
                onTimer += value; 
            }
            remove {
                onTimer -= value;
            } 
        }
 
       ///  
        /// 
        ///     
        ///       Disposes of the resources (other than memory) used by the timer.
        ///    
        /// 
        protected override void Dispose(bool disposing) { 
            if (disposing) {
                if (timerWindow != null) { 
                    timerWindow.StopTimer(); 
                }
 
                Enabled = false;
            }
            timerWindow = null;
            base.Dispose(disposing); 
        }
 
        ///  
        /// 
        ///     Indicates whether the timer is 
        ///       running.
        /// 
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.TimerEnabledDescr) 
        ] 
        public virtual bool Enabled {
            get { 
                if (timerWindow == null) {
                    return enabled;
                }
                return  timerWindow.IsTimerRunning; 
            }
 
            set { 
                lock(syncObj) {
 
                    if (enabled != value) {

                        enabled = value;
 
                        // At runtime, enable or disable the corresponding Windows timer
                        // 
                        if (!DesignMode) { 
                            if (value) {
 
                                // create the timer window if needed.
                                //
                                if (timerWindow == null) {
 
                                    timerWindow = new TimerNativeWindow(this);
                                } 
 
                                timerRoot = GCHandle.Alloc(this);
 
                                timerWindow.StartTimer(interval);
                            }
                            else{
                                if (timerWindow != null){ 
                                    timerWindow.StopTimer();
                                } 
 
                                if (timerRoot.IsAllocated) {
                                    timerRoot.Free(); 
                                }

                            }
                        } 

 
                    } 
                }
 
            }
        }

        ///  
        /// 
        ///     
        ///       Indicates the time, in milliseconds, between timer ticks. 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(100),
        SRDescription(SR.TimerIntervalDescr)
        ] 
        public int Interval {
            get { 
                return interval; 
            }
            set { 
                lock(syncObj) {
                    if (value < 1)
                        throw new ArgumentOutOfRangeException("Interval", SR.GetString(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture)));
 
                    if (interval != value) {
                        interval = value; 
                        if (Enabled) { 

                            Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?"); 
                            // just change the timer value, don't tear down the timer
                            // itself.
                            //
                            if (!DesignMode && timerWindow != null) { 
                                timerWindow.RestartTimer(value);
                            } 
                        } 
                    }
                } 
            }
        }

        ///  
        /// 
        /// Raises the  
        /// event. 
        /// 
        protected virtual void OnTick(EventArgs e) { 
            if (onTimer != null) onTimer(this, e);
        }

        ///  
        /// 
        ///    Starts the 
        ///       timer. 
        /// 
        public void Start() { 
            Enabled = true;
        }

        ///  
        /// 
        ///    Stops the 
        ///       timer. 
        /// 
        public void Stop() { 
            Enabled = false;
        }

        ///  
        /// 
        ///     returns us as a string. 
        ///  
        /// 
        public override string ToString() { 
            string s = base.ToString();
            return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture);
        }
 

        private class TimerNativeWindow : NativeWindow { 
 

            // the timer that owns us 
            //
            private Timer _owner;

            // our current id -- this is usally the same as TimerID but we also 
            // use it as a flag of when our timer is running.
            // 
            private int   _timerID; 

            // arbitrary timer ID. 
            //
            private static int    TimerID = 1;

            // setting this when we are stopping the timer so someone can't restart it in the process. 
            //
            private bool _stoppingTimer; 
 
            internal TimerNativeWindow(Timer owner) {
 
                this._owner = owner;
            }

            ~TimerNativeWindow() { 

 
 

                // note this call will work form the finalizer thread. 
                //
                StopTimer();
            }
 
            public bool IsTimerRunning {
                get { 
 
                    return _timerID != 0 && Handle != IntPtr.Zero;
                } 
            }


            // Ensures that our HWND has been created. 
            //
            private bool EnsureHandle() { 
                if (Handle == IntPtr.Zero) { 

 
                    // we create a totally vanilla invisible window just for WM_TIMER messages.
                    //
                    CreateParams cp = new CreateParams();
                    cp.Style = 0; 
                    cp.ExStyle = 0;
                    cp.ClassStyle = 0; 
                    cp.Caption = GetType().Name; 

                    // Message only windows are cheaper and have fewer issues than 
                    // full blown invisible windows.  But, they are only supported
                    // on NT.
                    if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
                        cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; 
                    }
 
                    CreateHandle(cp); 
                }
                Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!"); 
                return Handle != IntPtr.Zero;
            }

            // Returns true if we need to marshal across threads to access this timer's HWND. 
            //
            private bool GetInvokeRequired(IntPtr hWnd) { 
                if (hWnd != IntPtr.Zero) { 
                    int pid;
                    int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid); 
                    int currentThread = SafeNativeMethods.GetCurrentThreadId();
                    return(hwndThread != currentThread);
                }
                return false; 
            }
 
            // change the interval of the timer without destroying the HWND. 
            //
            public void RestartTimer(int newInterval) { 
                StopTimer(false, IntPtr.Zero);
                StartTimer(newInterval);
            }
 
            // Start the timer with the specified interval.
            // 
            public void StartTimer(int interval) { 

                if (_timerID == 0 && !_stoppingTimer) { 
                    if (EnsureHandle()) {
                        _timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero);
                    }
                } 
            }
 
            // stop the timer. 
            //
            public void StopTimer() { 

                StopTimer(true, IntPtr.Zero);
            }
 
            // stop the timer and optionally destroy the HWND.
            // 
            public void StopTimer(bool destroyHwnd, IntPtr hWnd) { 

 
                if (hWnd == IntPtr.Zero) {

                    hWnd = Handle;
                } 

                // Fire a message across threads to destroy the timer and HWND on the thread that created it. 
                // 
                if (GetInvokeRequired(hWnd)) {
                    UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0); 
                    return;
                }

                // Locking 'this' here is ok since this is an internal class.  See VSW#464499. 
                lock(this) {
 
                    if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) { 

                        return; 
                    }

                    if (_timerID != 0) {
 

                        try { 
                            _stoppingTimer = true; 
                            SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID);
                        } 
                        finally {
                            _timerID = 0;
                            _stoppingTimer = false;
                        } 

                    } 
 
                    if (destroyHwnd) {
                        base.DestroyHandle(); 
                    }
                }
            }
 
            // Destroy the handle, stopping the timer first.
            // 
            public override void DestroyHandle() { 
                // don't recurse!
                // 
                StopTimer(false, IntPtr.Zero);
                Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
                base.DestroyHandle();
            } 

            protected override void OnThreadException(Exception e) { 
                Application.OnThreadException(e); 
            }
 
            public override void ReleaseHandle() {
                // don't recurse!
                //
                StopTimer(false, IntPtr.Zero); 
                Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
 
                base.ReleaseHandle(); 
            }
 
            protected override void WndProc(ref Message m) {

                Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?");
 
                // for timer messages, make sure they're ours (it'll be wierd if they aren't)
                // and call the timer event. 
                // 
                if (m.Msg == NativeMethods.WM_TIMER) {
                    //Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?"); 
                    if ((int)m.WParam == _timerID) {
                        _owner.OnTick(EventArgs.Empty);
                        return;
                    } 
                }
                else if (m.Msg == NativeMethods.WM_CLOSE) { 
                    // this is a posted method from another thread that tells us we need 
                    // to kill the timer.  The handle may already be gone, so we specify it here.
                    // 
                    StopTimer(true, m.HWnd);
                    return;
                }
                base.WndProc(ref m); 
            }
 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK