Timer.cs 3.4 KB

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