2 // System.Threading.Timer.cs
5 // Dick Porter (dick@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Runtime.InteropServices;
33 namespace System.Threading
38 public sealed class Timer : MarshalByRefObject, IDisposable
40 sealed class Runner : MarshalByRefObject
42 ManualResetEvent wait;
43 AutoResetEvent start_event;
44 TimerCallback callback;
51 public Runner (TimerCallback callback, object state, AutoResetEvent start_event)
53 this.callback = callback;
55 this.start_event = start_event;
56 this.wait = new ManualResetEvent (false);
60 get { return dueTime; }
61 set { dueTime = value; }
65 get { return period; }
66 set { period = value == 0 ? Timeout.Infinite : value; }
69 bool WaitForDueTime ()
75 signaled = wait.WaitOne (dueTime, false);
76 } while (signaled == true && !disposed && !aborted);
98 public void Dispose ()
108 while (!disposed && start_event.WaitOne ()) {
114 if (dueTime == Timeout.Infinite)
117 if (!WaitForDueTime ())
120 if (aborted || (period == Timeout.Infinite))
123 bool signaled = false;
133 } catch (ObjectDisposedException) {
134 // FIXME: There is some race condition
135 // here when the thread is being
140 signaled = wait.WaitOne (period, false);
142 if (aborted || disposed)
147 } else if (!WaitForDueTime ()) {
156 AutoResetEvent start_event;
159 public Timer (TimerCallback callback, object state, int dueTime, int period)
162 throw new ArgumentOutOfRangeException ("dueTime");
165 throw new ArgumentOutOfRangeException ("period");
167 Init (callback, state, dueTime, period);
170 public Timer (TimerCallback callback, object state, long dueTime, long period)
173 throw new ArgumentOutOfRangeException ("dueTime");
176 throw new ArgumentOutOfRangeException ("period");
178 Init (callback, state, (int) dueTime, (int) period);
181 public Timer (TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
182 : this (callback, state, Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds))
186 [CLSCompliant(false)]
187 public Timer (TimerCallback callback, object state, uint dueTime, uint period)
188 : this (callback, state, (long) dueTime, (long) period)
193 public Timer (TimerCallback callback)
195 Init (callback, this, Timeout.Infinite, Timeout.Infinite);
199 void Init (TimerCallback callback, object state, int dueTime, int period)
201 start_event = new AutoResetEvent (false);
202 runner = new Runner (callback, state, start_event);
203 Change (dueTime, period);
204 t = new Thread (new ThreadStart (runner.Start));
205 t.IsBackground = true;
209 public bool Change (int dueTime, int period)
212 throw new ArgumentOutOfRangeException ("dueTime");
215 throw new ArgumentOutOfRangeException ("period");
220 start_event.Reset ();
222 runner.DueTime = dueTime;
223 runner.Period = period;
228 public bool Change (long dueTime, long period)
230 if(dueTime > 4294967294)
231 throw new NotSupportedException ("Due time too large");
233 if(period > 4294967294)
234 throw new NotSupportedException ("Period too large");
236 return Change ((int) dueTime, (int) period);
239 public bool Change (TimeSpan dueTime, TimeSpan period)
241 return Change (Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds));
244 [CLSCompliant(false)]
245 public bool Change (uint dueTime, uint period)
247 if (dueTime > Int32.MaxValue)
248 throw new NotSupportedException ("Due time too large");
250 if (period > Int32.MaxValue)
251 throw new NotSupportedException ("Period too large");
253 return Change ((int) dueTime, (int) period);
256 public void Dispose ()
258 if (t != null && t.IsAlive) {
259 if (t != Thread.CurrentThread)
265 GC.SuppressFinalize (this);
268 public bool Dispose (WaitHandle notifyObject)
271 NativeEventCalls.SetEvent_internal (notifyObject.Handle);
277 if (t != null && t.IsAlive)