Timer.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //
  2. // System.Threading.Timer.cs
  3. //
  4. // Authors:
  5. // Dick Porter ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
  9. //
  10. namespace System.Threading
  11. {
  12. public sealed class Timer : MarshalByRefObject, IDisposable
  13. {
  14. sealed class Runner : MarshalByRefObject, IDisposable
  15. {
  16. ManualResetEvent wait;
  17. AutoResetEvent start_event;
  18. TimerCallback callback;
  19. object state;
  20. int dueTime;
  21. int period;
  22. bool disposed;
  23. bool aborted;
  24. public Runner (TimerCallback callback, object state, AutoResetEvent start_event)
  25. {
  26. this.callback = callback;
  27. this.state = state;
  28. this.start_event = start_event;
  29. this.wait = new ManualResetEvent (false);
  30. }
  31. public int DueTime {
  32. get { return dueTime; }
  33. set { dueTime = value; }
  34. }
  35. public int Period {
  36. get { return period; }
  37. set { period = value == 0 ? Timeout.Infinite : value; }
  38. }
  39. bool WaitForDueTime ()
  40. {
  41. if (dueTime > 0) {
  42. bool signaled;
  43. do {
  44. wait.Reset ();
  45. signaled = wait.WaitOne (dueTime, false);
  46. } while (signaled == true && !disposed && !aborted);
  47. if (!signaled)
  48. callback (state);
  49. if (disposed)
  50. return false;
  51. }
  52. return true;
  53. }
  54. public void Abort ()
  55. {
  56. lock (this) {
  57. aborted = true;
  58. wait.Set ();
  59. }
  60. }
  61. public void Start ()
  62. {
  63. while (start_event.WaitOne ()) {
  64. aborted = false;
  65. if (dueTime == Timeout.Infinite)
  66. continue;
  67. if (!WaitForDueTime ())
  68. return;
  69. if (aborted || (period == Timeout.Infinite))
  70. continue;
  71. bool signaled = false;
  72. while (true) {
  73. wait.Reset ();
  74. signaled = wait.WaitOne (period, false);
  75. if (disposed)
  76. return;
  77. if (aborted)
  78. break;
  79. if (!signaled) {
  80. callback (state);
  81. } else if (!WaitForDueTime ()) {
  82. return;
  83. }
  84. }
  85. }
  86. }
  87. public void Dispose ()
  88. {
  89. Dispose (true);
  90. }
  91. void Dispose (bool disposing)
  92. {
  93. disposed = true;
  94. if (wait != null) {
  95. wait.Set ();
  96. Thread.Sleep (100);
  97. ((IDisposable) wait).Dispose ();
  98. wait = null;
  99. }
  100. if (disposing)
  101. GC.SuppressFinalize (this);
  102. }
  103. ~Runner ()
  104. {
  105. Dispose (false);
  106. }
  107. }
  108. Runner runner;
  109. AutoResetEvent start_event;
  110. public Timer (TimerCallback callback, object state, int dueTime, int period)
  111. {
  112. if (dueTime < -1)
  113. throw new ArgumentOutOfRangeException ("dueTime");
  114. if (period < -1)
  115. throw new ArgumentOutOfRangeException ("period");
  116. Init (callback, state, dueTime, period);
  117. }
  118. public Timer (TimerCallback callback, object state, long dueTime, long period)
  119. {
  120. if (dueTime < -1)
  121. throw new ArgumentOutOfRangeException ("dueTime");
  122. if (period < -1)
  123. throw new ArgumentOutOfRangeException ("period");
  124. Init (callback, state, (int) dueTime, (int) period);
  125. }
  126. public Timer (TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
  127. : this (callback, state, Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds))
  128. {
  129. }
  130. [CLSCompliant(false)]
  131. public Timer (TimerCallback callback, object state, uint dueTime, uint period)
  132. : this (callback, state, (long) dueTime, (long) period)
  133. {
  134. }
  135. void Init (TimerCallback callback, object state, int dueTime, int period)
  136. {
  137. start_event = new AutoResetEvent (false);
  138. runner = new Runner (callback, state, start_event);
  139. Change (dueTime, period);
  140. Thread t = new Thread (new ThreadStart (runner.Start));
  141. t.IsBackground = true;
  142. t.Start ();
  143. }
  144. [MonoTODO("false return?")]
  145. public bool Change (int dueTime, int period)
  146. {
  147. if (dueTime < -1)
  148. throw new ArgumentOutOfRangeException ("dueTime");
  149. if (period < -1)
  150. throw new ArgumentOutOfRangeException ("period");
  151. runner.DueTime = dueTime;
  152. runner.Period = period;
  153. runner.Abort ();
  154. start_event.Set ();
  155. return true;
  156. }
  157. public bool Change (long dueTime, long period)
  158. {
  159. if(dueTime > 4294967294)
  160. throw new NotSupportedException ("Due time too large");
  161. if(period > 4294967294)
  162. throw new NotSupportedException ("Period too large");
  163. return Change ((int) dueTime, (int) period);
  164. }
  165. public bool Change (TimeSpan dueTime, TimeSpan period)
  166. {
  167. return Change (Convert.ToInt32(dueTime.TotalMilliseconds), Convert.ToInt32(period.TotalMilliseconds));
  168. }
  169. [CLSCompliant(false)]
  170. public bool Change (uint dueTime, uint period)
  171. {
  172. if (dueTime > Int32.MaxValue)
  173. throw new NotSupportedException ("Due time too large");
  174. if (period > Int32.MaxValue)
  175. throw new NotSupportedException ("Period too large");
  176. return Change ((int) dueTime, (int) period);
  177. }
  178. public void Dispose ()
  179. {
  180. runner.Dispose ();
  181. runner = null;
  182. GC.SuppressFinalize (this);
  183. }
  184. [MonoTODO("How do we signal the handler?")]
  185. public bool Dispose (WaitHandle notifyObject)
  186. {
  187. Dispose ();
  188. return true; //FIXME
  189. }
  190. ~Timer ()
  191. {
  192. runner = null;
  193. }
  194. }
  195. }