RegisteredWaitHandle.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // System.Threading.RegisteredWaitHandle.cs
  3. //
  4. // Author:
  5. // Dick Porter ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // (C) Ximian, Inc. http://www.ximian.com
  9. //
  10. namespace System.Threading
  11. {
  12. public sealed class RegisteredWaitHandle : MarshalByRefObject
  13. {
  14. WaitHandle _waitObject;
  15. WaitOrTimerCallback _callback;
  16. TimeSpan _timeout;
  17. object _state;
  18. bool _executeOnlyOnce;
  19. WaitHandle _finalEvent;
  20. ManualResetEvent _cancelEvent;
  21. int _callsInProcess;
  22. bool _unregistered;
  23. internal RegisteredWaitHandle (WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce)
  24. {
  25. _waitObject = waitObject;
  26. _callback = callback;
  27. _state = state;
  28. _timeout = timeout;
  29. _executeOnlyOnce = executeOnlyOnce;
  30. _finalEvent = null;
  31. _cancelEvent = new ManualResetEvent (false);
  32. _callsInProcess = 0;
  33. _unregistered = false;
  34. }
  35. internal void Wait (object state)
  36. {
  37. try
  38. {
  39. WaitHandle[] waits = new WaitHandle[] {_waitObject, _cancelEvent};
  40. do
  41. {
  42. int signal = WaitHandle.WaitAny (waits, _timeout, false);
  43. if (!_unregistered)
  44. {
  45. lock (this) { _callsInProcess++; }
  46. ThreadPool.QueueUserWorkItem (new WaitCallback (DoCallBack), (signal == WaitHandle.WaitTimeout));
  47. }
  48. }
  49. while (!_unregistered && !_executeOnlyOnce);
  50. }
  51. catch {}
  52. lock (this) {
  53. _unregistered = true;
  54. if (_callsInProcess == 0 && _finalEvent != null)
  55. NativeEventCalls.SetEvent_internal (_finalEvent.Handle);
  56. }
  57. }
  58. private void DoCallBack (object timedOut)
  59. {
  60. if (_callback != null)
  61. _callback (_state, (bool)timedOut);
  62. lock (this)
  63. {
  64. _callsInProcess--;
  65. if (_unregistered && _callsInProcess == 0 && _finalEvent != null)
  66. NativeEventCalls.SetEvent_internal (_finalEvent.Handle);
  67. }
  68. }
  69. public bool Unregister(WaitHandle waitObject)
  70. {
  71. lock (this)
  72. {
  73. if (_unregistered) return false;
  74. _finalEvent = waitObject;
  75. _unregistered = true;
  76. _cancelEvent.Set();
  77. return true;
  78. }
  79. }
  80. [MonoTODO]
  81. ~RegisteredWaitHandle() {
  82. // FIXME
  83. }
  84. }
  85. }