2004-05-11 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System / System.Timers / Timer.cs
1 //
2 // System.Timers.Timer
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002 Ximian, Inc (http://www.ximian.com)
8 //
9 // The docs talk about server timers and such...
10
11 using System;
12 using System.ComponentModel;
13 using System.Threading;
14
15 namespace System.Timers
16 {
17         [DefaultEventAttribute("Elapsed")]
18         [DefaultProperty("Interval")]
19         public class Timer : Component, ISupportInitialize
20         {
21                 bool autoReset;
22                 bool enabled;
23                 double interval;
24                 ISynchronizeInvoke so;
25                 ManualResetEvent wait;
26
27                 [Category("Behavior")]
28                 [TimersDescription("Occurs when the Interval has elapsed.")]
29                 public event ElapsedEventHandler Elapsed;
30
31                 public Timer () : this (100)
32                 {
33                 }
34
35                 public Timer (double interval)
36                 {
37                         autoReset = true;
38                         enabled = false;
39                         Interval = interval;
40                         so = null;
41                         wait = null;
42                 }
43
44
45                 [Category("Behavior")]
46                 [DefaultValue(true)]
47                 [TimersDescription("Indicates whether the timer will be restarted when it is enabled.")]
48                 public bool AutoReset
49                 {
50                         get { return autoReset; }
51                         set { autoReset = value; }
52                 }
53
54                 [Category("Behavior")]
55                 [DefaultValue(false)]
56                 [TimersDescription("Indicates whether the timer is enabled to fire events at a defined interval.")]
57                 public bool Enabled
58                 {
59                         get { return enabled; }
60                         set {
61                                 if (enabled == value)
62                                         return;
63
64                                 enabled = value;
65                                 if (value) {
66                                         Thread t = new Thread (new ThreadStart (StartTimer));
67                                         t.Start ();
68                                 } else {
69                                         StopTimer ();
70                                 }
71                         }
72                 }
73
74                 [Category("Behavior")]
75                 [DefaultValue(100)]
76                 [RecommendedAsConfigurable(true)]
77                 [TimersDescription( "The number of milliseconds between timer events.")]
78                 public double Interval
79                 {
80                         get { return interval; }
81                         set { 
82                                 // The doc says 'less than 0', but 0 also throws the exception
83                                 if (value <= 0)
84                                         throw new ArgumentException ("Invalid value: " + interval, "interval");
85
86                                 interval = value;
87                         }
88                 }
89
90                 public override ISite Site
91                 {
92                         get { return base.Site; }
93                         set { base.Site = value; }
94                 }
95
96                 [DefaultValue(null)]
97                 [TimersDescriptionAttribute("The object used to marshal the event handler calls issued " +
98                                             "when an interval has elapsed.")]
99                 public ISynchronizeInvoke SynchronizingObject
100                 {
101                         get { return so; }
102                         set { so = value; }
103                 }
104
105                 public void BeginInit ()
106                 {
107                         // Nothing to do
108                 }
109
110                 public void Close ()
111                 {
112                         StopTimer ();
113                 }
114
115                 public void EndInit ()
116                 {
117                         // Nothing to do
118                 }
119
120                 public void Start ()
121                 {
122                         Enabled = true;
123                 }
124
125                 public void Stop ()
126                 {
127                         Enabled = false;
128                 }
129
130                 protected override void Dispose (bool disposing)
131                 {
132                         Close ();
133                         base.Dispose (disposing);
134                 }
135
136                 static void Callback (object state)
137                 {
138                         Timer timer = (Timer) state;
139                         if (timer.Elapsed == null)
140                                 return;
141
142                         ElapsedEventArgs arg = new ElapsedEventArgs (DateTime.Now);
143
144                         if (timer.so != null && timer.so.InvokeRequired) {
145                                 timer.so.BeginInvoke (timer.Elapsed, new object [2] {timer, arg});
146                         } else {
147                                 timer.Elapsed (timer, arg);
148                         }
149                 }
150
151                 void StartTimer ()
152                 {
153                         wait = new ManualResetEvent (false);
154
155                         WaitCallback wc = new WaitCallback (Callback);
156                         while (enabled && wait.WaitOne ((int) interval, false) == false) {
157                                 if (autoReset == false)
158                                         enabled = false;
159
160                                 ThreadPool.QueueUserWorkItem (wc, this);
161                         }
162                         
163                         wc = null;
164                         ((IDisposable) wait).Dispose ();
165                         wait = null;
166                 }
167
168                 void StopTimer ()
169                 {
170                         if (wait != null)
171                                 wait.Set ();
172                 }
173         }
174 }
175