ThreadedRootStateMachine.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System;
  2. using System.Threading;
  3. using Wayne.Lib.Log;
  4. namespace Wayne.Lib.StateEngine
  5. {
  6. /// <summary>
  7. /// Threaded root state machine is the class that is driving a normal asynchronous state machine. It
  8. /// contains the logic for running a statemachine in a separate thread.
  9. /// </summary>
  10. //[System.Diagnostics.DebuggerNonUserCode()]
  11. internal class ThreadedRootStateMachine : EventBufferingRootStateMachine
  12. {
  13. #region Fields
  14. private System.Threading.Thread thread;
  15. private AutoResetEvent eventReceivedEvent = new AutoResetEvent(false);
  16. private AutoResetEvent threadStartedEvent = new AutoResetEvent(false);
  17. private bool threadTerminated;
  18. #endregion
  19. #region Construction
  20. /// <summary>
  21. /// Initializes a new instance of the ThreadedRootStateMachine class.
  22. /// </summary>
  23. /// <param name="name">The name of the statemachine.</param>
  24. /// <param name="debugLogger">The DebugLogger to use.</param>
  25. /// <param name="logCategory">The log category.</param>
  26. public ThreadedRootStateMachine(string name, IDebugLogger debugLogger, object logCategory)
  27. : base(name, debugLogger, logCategory)
  28. {
  29. thread = new System.Threading.Thread(new System.Threading.ThreadStart(Execute));
  30. }
  31. #endregion
  32. #region Private methods
  33. /// <summary>
  34. /// Thread method.
  35. /// </summary>
  36. private void Execute()
  37. {
  38. try
  39. {
  40. Initialize();
  41. PerformInitialTransition();
  42. //Signal to the thread calling Start() that it can continue to execute.
  43. threadStartedEvent.Set();
  44. CreateOnStateChangeEventHandler(this);
  45. while (!threadTerminated)
  46. {
  47. //Wait for new event to be added to the queue.
  48. eventReceivedEvent.WaitOne();
  49. if (!threadTerminated)
  50. {
  51. //Read out the event
  52. HandleQueuedEvents(null);
  53. }
  54. }
  55. }
  56. catch (Exception exception)
  57. {
  58. throw new StateEngineException(string.Format("Unexpected Exception in Execute(). StateMachine \"{0}\"", this.Name), exception);
  59. }
  60. }
  61. #endregion
  62. #region Public Methods
  63. /// <summary>
  64. /// Entry point for incoming events. The base functionality is removed, and moved into the thread.
  65. /// This method only puts the message into the event list, and signals to the thread that a new event has been added.
  66. /// </summary>
  67. /// <param name="stateEngineEvent"></param>
  68. public override void IncomingEvent(StateEngineEvent stateEngineEvent)
  69. {
  70. //Base EventBufferingRootStateMachine takes care of queueing the event.
  71. base.IncomingEvent(stateEngineEvent);
  72. //Signal to the thread that there is a new event to handle.
  73. if (eventReceivedEvent != null)
  74. eventReceivedEvent.Set();
  75. }
  76. /// <summary>
  77. /// Starts the state machine. The base functionality is removed and moved to the thread.
  78. /// </summary>
  79. public override void Start()
  80. {
  81. //Start the thread
  82. thread.Name = this.Name;
  83. thread.Start();
  84. //Wait until the thread is really started and initialized.
  85. threadStartedEvent.WaitOne();
  86. }
  87. #endregion
  88. #region Protected Methods
  89. /// <summary>
  90. /// Disposes the resources owned by the instance.
  91. /// </summary>
  92. /// <param name="disposing"></param>
  93. protected override void Dispose(bool disposing)
  94. {
  95. if (!disposed)
  96. {
  97. this.threadTerminated = true;
  98. eventReceivedEvent.Set();
  99. if (this.Started)
  100. {
  101. // JDL, MAR-02-10, wait up to 1 sec
  102. if (!thread.Join(1000))
  103. thread.Abort();
  104. thread = null;
  105. }
  106. if (eventReceivedEvent != null)
  107. {
  108. eventReceivedEvent.Close();
  109. eventReceivedEvent = null;
  110. }
  111. if (threadStartedEvent != null)
  112. {
  113. threadStartedEvent.Close();
  114. threadStartedEvent = null;
  115. }
  116. }
  117. base.Dispose(disposing);
  118. }
  119. #endregion
  120. }
  121. }