PageRenderTime 76ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/ReactorUtilities/BlockingThreadInvoker.cs

https://bitbucket.org/VahidN/interlace
C# | 174 lines | 106 code | 33 blank | 35 comment | 8 complexity | 6f37782f6c63642d007e9fd5bf97e3e9 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. using System.Threading;
  31. using System.Windows.Forms;
  32. using Interlace.ReactorCore;
  33. using Interlace.Utilities;
  34. #endregion
  35. namespace Interlace.ReactorUtilities
  36. {
  37. /// <summary>
  38. /// An <see cref="IThreadInvoker"/> implementation that blocks. Great care should be taken
  39. /// when using this class; see the remarks.
  40. /// </summary>
  41. /// <remarks>
  42. /// This class should only be used for testing. There are a number of traps when using it.
  43. /// First, if the called method needs a running UI thread or reactor thread, a deadlock will
  44. /// most likely occur. Also, the callbacks will fail as soon as this object is disposed, which
  45. /// may be too soon.
  46. /// </remarks>
  47. public class BlockingThreadInvoker : IDisposable, IThreadInvoker
  48. {
  49. AutoResetEvent _requestSignal;
  50. AutoResetEvent _responseSignal;
  51. object _requestLock = new object();
  52. Delegate _requestDelegate = null;
  53. object[] _requestArguments = null;
  54. object _responseResult = null;
  55. bool _disposed = false;
  56. public BlockingThreadInvoker()
  57. {
  58. _requestSignal = new AutoResetEvent(false);
  59. _responseSignal = new AutoResetEvent(false);
  60. }
  61. public void Dispose()
  62. {
  63. lock (_requestLock)
  64. {
  65. _disposed = true;
  66. }
  67. if (_requestSignal != null)
  68. {
  69. _requestSignal.Close();
  70. _requestSignal = null;
  71. }
  72. if (_responseSignal != null)
  73. {
  74. _responseSignal.Close();
  75. _responseSignal = null;
  76. }
  77. }
  78. object WaitOnInternal(DeferredObject deferred)
  79. {
  80. object result = null;
  81. Exception exception = null;
  82. bool completed = false;
  83. deferred.ObjectCompletion(
  84. delegate(object deferredResult)
  85. {
  86. result = deferredResult;
  87. completed = true;
  88. return null;
  89. },
  90. delegate(DeferredFailure failure)
  91. {
  92. exception = failure.Exception;
  93. completed = true;
  94. return null;
  95. }, null);
  96. while (!completed)
  97. {
  98. _requestSignal.WaitOne();
  99. _responseResult = _requestDelegate.DynamicInvoke(_requestArguments);
  100. _requestDelegate = null;
  101. _requestArguments = null;
  102. _responseSignal.Set();
  103. }
  104. if (exception != null)
  105. {
  106. throw new ApplicationException(
  107. "An exception was thrown while running callbacks. Check InnerException for details.", exception);
  108. }
  109. return result;
  110. }
  111. public void WaitOn(VoidDeferred deferred)
  112. {
  113. WaitOnInternal(deferred);
  114. }
  115. public T WaitOn<T>(Deferred<T> deferred)
  116. {
  117. return (T)WaitOnInternal(deferred);
  118. }
  119. #region IThreadInvoker Members
  120. public object Invoke(Delegate method)
  121. {
  122. return Invoke(method, new object[] { });
  123. }
  124. public object Invoke(Delegate method, params object[] args)
  125. {
  126. lock (_requestLock)
  127. {
  128. if (_disposed) throw new InvalidOperationException(
  129. "The blocking thread invoker has been disposed; invokes should not be made.");
  130. _requestDelegate = method;
  131. _requestArguments = args;
  132. _requestSignal.Set();
  133. _responseSignal.WaitOne();
  134. object result = _responseResult;
  135. _responseResult = null;
  136. return result;
  137. }
  138. }
  139. #endregion
  140. }
  141. }