1 using System; 2 using System.ComponentModel; 3 using System.Globalization; 4 using System.Runtime; 5 using System.Runtime.InteropServices; 6 using System.Threading; 7 namespace System.Windows.Forms 8 { 9 [DefaultEvent("Tick"), DefaultProperty("Interval"), ToolboxItemFilter("System.Windows.Forms"), SRDescription("DescriptionTimer")] 10 public class Timer : Component 11 { 12 private class TimerNativeWindow : NativeWindow 13 { 14 private Timer _owner; 15 private int _timerID; 16 private static int TimerID = 1; 17 private bool _stoppingTimer; 18 public bool IsTimerRunning 19 { 20 get 21 { 22 return this._timerID != 0 && base.Handle != IntPtr.Zero; 23 } 24 } 25 ~TimerNativeWindow() 26 { 27 this.StopTimer(); 28 } 29 public void RestartTimer(int newInterval) 30 { 31 this.StopTimer(false, IntPtr.Zero); 32 this.StartTimer(newInterval); 33 } 34 public void StartTimer(int interval) 35 { 36 if (this._timerID == 0 && !this._stoppingTimer && this.EnsureHandle()) 37 { 38 this._timerID = (int)SafeNativeMethods.SetTimer(new HandleRef(this, base.Handle), Timer.TimerNativeWindow.TimerID++, interval, IntPtr.Zero); 39 } 40 } 41 public void StopTimer() 42 { 43 this.StopTimer(true, IntPtr.Zero); 44 } 45 public void StopTimer(bool destroyHwnd, IntPtr hWnd) 46 { 47 if (hWnd == IntPtr.Zero) 48 { 49 hWnd = base.Handle; 50 } 51 if (this.GetInvokeRequired(hWnd)) 52 { 53 UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), 16, 0, 0); 54 return; 55 } 56 bool flag = false; 57 try 58 { 59 Monitor.Enter(this, ref flag); 60 if (!this._stoppingTimer && !(hWnd == IntPtr.Zero) && UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) 61 { 62 if (this._timerID != 0) 63 { 64 try 65 { 66 this._stoppingTimer = true; 67 SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), this._timerID); 68 } 69 finally 70 { 71 this._timerID = 0; 72 this._stoppingTimer = false; 73 } 74 } 75 if (destroyHwnd) 76 { 77 base.DestroyHandle(); 78 } 79 } 80 } 81 finally 82 { 83 if (flag) 84 { 85 Monitor.Exit(this); 86 } 87 } 88 } 89 public override void DestroyHandle() 90 { 91 this.StopTimer(false, IntPtr.Zero); 92 base.DestroyHandle(); 93 } 94 protected override void OnThreadException(Exception e) 95 { 96 Application.OnThreadException(e); 97 } 98 public override void ReleaseHandle() 99 { 100 this.StopTimer(false, IntPtr.Zero); 101 base.ReleaseHandle(); 102 } 103 protected override void WndProc(ref Message m) 104 { 105 if (m.Msg == 275) 106 { 107 if ((int)((long)m.WParam) == this._timerID) 108 { 109 this._owner.OnTick(EventArgs.Empty); 110 return; 111 } 112 } 113 else 114 { 115 if (m.Msg == 16) 116 { 117 this.StopTimer(true, m.HWnd); 118 return; 119 } 120 } 121 base.WndProc(ref m); 122 } 123 internal TimerNativeWindow(Timer owner) 124 { 125 this._owner = owner; 126 } 127 private bool EnsureHandle() 128 { 129 if (base.Handle == IntPtr.Zero) 130 { 131 CreateParams createParams = new CreateParams(); 132 createParams.Style = 0; 133 createParams.ExStyle = 0; 134 createParams.ClassStyle = 0; 135 createParams.Caption = base.GetType().Name; 136 if (Environment.OSVersion.Platform == PlatformID.Win32NT) 137 { 138 createParams.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; 139 } 140 this.CreateHandle(createParams); 141 } 142 return base.Handle != IntPtr.Zero; 143 } 144 private bool GetInvokeRequired(IntPtr hWnd) 145 { 146 if (hWnd != IntPtr.Zero) 147 { 148 int num; 149 int windowThreadProcessId = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out num); 150 int currentThreadId = SafeNativeMethods.GetCurrentThreadId(); 151 return windowThreadProcessId != currentThreadId; 152 } 153 return false; 154 } 155 } 156 private int interval; 157 private bool enabled; 158 private EventHandler onTimer; 159 private GCHandle timerRoot; 160 private Timer.TimerNativeWindow timerWindow; 161 private object userData; 162 private object syncObj = new object(); 163 [SRCategory("CatBehavior"), SRDescription("TimerTimerDescr")] 164 public event EventHandler Tick 165 { 166 add 167 { 168 this.onTimer = (EventHandler)Delegate.Combine(this.onTimer, value); 169 } 170 remove 171 { 172 this.onTimer = (EventHandler)Delegate.Remove(this.onTimer, value); 173 } 174 } 175 [Bindable(true), DefaultValue(null), Localizable(false), TypeConverter(typeof(StringConverter)), SRCategory("CatData"), SRDescription("ControlTagDescr")] 176 public object Tag 177 { 178 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 179 get 180 { 181 return this.userData; 182 } 183 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 184 set 185 { 186 this.userData = value; 187 } 188 } 189 [DefaultValue(false), SRCategory("CatBehavior"), SRDescription("TimerEnabledDescr")] 190 public virtual bool Enabled 191 { 192 get 193 { 194 if (this.timerWindow == null) 195 { 196 return this.enabled; 197 } 198 return this.timerWindow.IsTimerRunning; 199 } 200 set 201 { 202 lock (this.syncObj) 203 { 204 if (this.enabled != value) 205 { 206 this.enabled = value; 207 if (!base.DesignMode) 208 { 209 if (value) 210 { 211 if (this.timerWindow == null) 212 { 213 this.timerWindow = new Timer.TimerNativeWindow(this); 214 } 215 this.timerRoot = GCHandle.Alloc(this); 216 this.timerWindow.StartTimer(this.interval); 217 } 218 else 219 { 220 if (this.timerWindow != null) 221 { 222 this.timerWindow.StopTimer(); 223 } 224 if (this.timerRoot.IsAllocated) 225 { 226 this.timerRoot.Free(); 227 } 228 } 229 } 230 } 231 } 232 } 233 } 234 [DefaultValue(100), SRCategory("CatBehavior"), SRDescription("TimerIntervalDescr")] 235 public int Interval 236 { 237 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 238 get 239 { 240 return this.interval; 241 } 242 set 243 { 244 lock (this.syncObj) 245 { 246 if (value < 1) 247 { 248 throw new ArgumentOutOfRangeException("Interval", SR.GetString("TimerInvalidInterval", new object[] 249 { 250 value, 251 0.ToString(CultureInfo.CurrentCulture) 252 })); 253 } 254 if (this.interval != value) 255 { 256 this.interval = value; 257 if (this.Enabled && !base.DesignMode && this.timerWindow != null) 258 { 259 this.timerWindow.RestartTimer(value); 260 } 261 } 262 } 263 } 264 } 265 public Timer() 266 { 267 this.interval = 100; 268 } 269 public Timer(IContainer container) : this() 270 { 271 if (container == null) 272 { 273 throw new ArgumentNullException("container"); 274 } 275 container.Add(this); 276 } 277 protected override void Dispose(bool disposing) 278 { 279 if (disposing) 280 { 281 if (this.timerWindow != null) 282 { 283 this.timerWindow.StopTimer(); 284 } 285 this.Enabled = false; 286 } 287 this.timerWindow = null; 288 base.Dispose(disposing); 289 } 290 protected virtual void OnTick(EventArgs e) 291 { 292 if (this.onTimer != null) 293 { 294 this.onTimer(this, e); 295 } 296 } 297 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 298 public void Start() 299 { 300 this.Enabled = true; 301 } 302 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 303 public void Stop() 304 { 305 this.Enabled = false; 306 } 307 public override string ToString() 308 { 309 string str = base.ToString(); 310 return str + ", Interval: " + this.Interval.ToString(CultureInfo.CurrentCulture); 311 } 312 } 313 }
以上代码是通过ILSpy反编译出来的,学习的心得如下:
1、Start和Stop方法,都是通过设置Enabled属性启用或停用定时器
2、Interval用来设置定时器的运行时间间隔
3、设置Interval注意以下代码:
1 public int Interval 2 { 3 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 4 get 5 { 6 return this.interval; 7 } 8 set 9 { 10 lock (this.syncObj) 11 { 12 if (value < 1) 13 { 14 throw new ArgumentOutOfRangeException("Interval", SR.GetString("TimerInvalidInterval", new object[] 15 { 16 value, 17 0.ToString(CultureInfo.CurrentCulture) 18 })); 19 } 20 if (this.interval != value) 21 { 22 this.interval = value; 23 if (this.Enabled && !base.DesignMode && this.timerWindow != null) 24 { 25 this.timerWindow.RestartTimer(value); 26 } 27 } 28 } 29 } 30 }
4、默认Timter的时间间隔为100毫秒。
1 public Timer() 2 { 3 this.interval = 100; 4 }
5、重写了ToString方法
1 public override string ToString() 2 { 3 string str = base.ToString(); 4 return str + ", Interval: " + this.Interval.ToString(CultureInfo.CurrentCulture); 5 }